1. Introduction and Aims

We have quality-controlled the 10X data and the SS2 data and now are left with the following objects:

10X 5K data - pb_sex_filtered

10X 30K data - pb_30k_sex_filtered

SS2 mutant data - ss2_mutants_final

2. Read in the data

Load/Install the Required Packages

[1] "patchwork is loaded correctly"

Attaching package: ‘viridis’

The following object is masked from ‘package:viridisLite’:

    viridis.map
[1] "viridis is loaded correctly"
[1] "Seurat is loaded correctly"
Loading required package: cowplot

Attaching package: ‘cowplot’

The following object is masked from ‘package:patchwork’:

    align_plots
[1] "cowplot is loaded correctly"
Loading required package: gridExtra
[1] "gridExtra is loaded correctly"
Loading required package: grid
[1] "grid is loaded correctly"
Loading required package: Hmisc
Loading required package: lattice
Loading required package: survival
Loading required package: Formula
Loading required package: ggplot2

Attaching package: ‘Hmisc’

The following object is masked from ‘package:Seurat’:

    Key

The following objects are masked from ‘package:base’:

    format.pval, units
[1] "Hmisc is loaded correctly"
Loading required package: reshape2
[1] "reshape2 is loaded correctly"
Loading required package: dplyr

Attaching package: ‘dplyr’

The following objects are masked from ‘package:Hmisc’:

    src, summarize

The following object is masked from ‘package:gridExtra’:

    combine

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
[1] "dplyr is loaded correctly"
Loading required package: Nebulosa
[1] "Nebulosa is loaded correctly"
Loading required package: monocle3
Loading required package: Biobase
Loading required package: BiocGenerics
Loading required package: parallel

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:parallel’:

    clusterApply, clusterApplyLB, clusterCall, clusterEvalQ,
    clusterExport, clusterMap, parApply, parCapply, parLapply,
    parLapplyLB, parRapply, parSapply, parSapplyLB

The following objects are masked from ‘package:dplyr’:

    combine, intersect, setdiff, union

The following object is masked from ‘package:gridExtra’:

    combine

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colnames,
    dirname, do.call, duplicated, eval, evalq, Filter, Find, get, grep,
    grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget,
    order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind,
    Reduce, rownames, sapply, setdiff, sort, table, tapply, union,
    unique, unsplit, which, which.max, which.min

Welcome to Bioconductor

    Vignettes contain introductory material; view with
    'browseVignettes()'. To cite Bioconductor, see 'citation("Biobase")',
    and for packages 'citation("pkgname")'.


Attaching package: ‘Biobase’

The following object is masked from ‘package:Hmisc’:

    contents

Loading required package: SingleCellExperiment
Loading required package: SummarizedExperiment
Loading required package: GenomicRanges
Loading required package: stats4
Loading required package: S4Vectors

Attaching package: ‘S4Vectors’

The following objects are masked from ‘package:dplyr’:

    first, rename

The following object is masked from ‘package:base’:

    expand.grid

Loading required package: IRanges

Attaching package: ‘IRanges’

The following objects are masked from ‘package:dplyr’:

    collapse, desc, slice

Loading required package: GenomeInfoDb
Loading required package: DelayedArray
Loading required package: matrixStats

Attaching package: ‘matrixStats’

The following objects are masked from ‘package:Biobase’:

    anyMissing, rowMedians

The following object is masked from ‘package:dplyr’:

    count


Attaching package: ‘DelayedArray’

The following objects are masked from ‘package:matrixStats’:

    colMaxs, colMins, colRanges, rowMaxs, rowMins, rowRanges

The following objects are masked from ‘package:base’:

    aperm, apply, rowsum


Attaching package: ‘SummarizedExperiment’

The following object is masked from ‘package:Seurat’:

    Assays


Attaching package: ‘monocle3’

The following objects are masked from ‘package:Biobase’:

    exprs, fData, fData<-, pData, pData<-
[1] "monocle3 is loaded correctly"

Read in the Data

screen hits

## EDIT - change this to the excel table once we have it finalized for the screen
screen_hits <- c("PBANKA-0516300",
"PBANKA-1217700",
"PBANKA-0409100",
"PBANKA-1034300",
"PBANKA-1437500",
"PBANKA-0827500",
"PBANKA-0824300",
"PBANKA-1426900",
"PBANKA-0105300",
"PBANKA-0921100",
"PBANKA-1002400",
"PBANKA-0829400",
"PBANKA-1347200",
"PBANKA-0828000",
"PBANKA-0902300",
"PBANKA-1418100",
"PBANKA-1435200",
"PBANKA-1454800",
"PBANKA-0712300",
"PBANKA-0410500",
"PBANKA-1144800",
"PBANKA-1231600",
"PBANKA-0503200",
"PBANKA-0308900",
"PBANKA-1214700",
"PBANKA-0709900",
"PBANKA-0311900",
"PBANKA-0716500",
"PBANKA-1447900",
"PBANKA-0102200",
"PBANKA-0713500",
"PBANKA-0102400",
"PBANKA-1302700",
"PBANKA-1235900",
"PBANKA-0401100",
"PBANKA-0413400",
"PBANKA-1126900",
"PBANKA-1425900",
"PBANKA-0418300",
"PBANKA-1464600",
"PBANKA-0806000")

Read in gene annotations

gene_annotations <- read.table("../data/Reference/GenesByTaxon_Summary.csv", header = TRUE, sep = ",", stringsAsFactors = TRUE)
dim(gene_annotations)

## convert _ to -
gene_annotations$Gene.ID <- gsub("_", "-", gene_annotations$Gene.ID)

load in datasets

paste("10x dataset")
[1] "10x dataset"
pb_sex_filtered
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("Smart-seq2 dataset")
[1] "Smart-seq2 dataset"
ss2_mutants_final
An object of class Seurat 
5245 features across 2717 samples within 1 assay 
Active assay: RNA (5245 features, 2000 variable features)
 2 dimensional reductions calculated: pca, umap
paste("The composition of the Smart-seq2 dataset is:")
[1] "The composition of the Smart-seq2 dataset is:"
table(ss2_mutants_final@meta.data$genotype)

Mutant     WT 
  2028    689 

3. Merging the Smart-seq2 and 10X Data

Prepare data

tenx_5k_counts_to_integrate
An object of class Seurat 
5098 features across 6191 samples within 1 assay 
Active assay: RNA (5098 features, 0 variable features)

We need to make sure the mutant data is compatible with the 10X data. the 10X data has fewer genes represented so we need to find the intersect of the two before integration.

GCSKO_mutants
An object of class Seurat 
5018 features across 2717 samples within 1 assay 
Active assay: RNA (5018 features, 0 variable features)
## double check that this is the same number of genes
## subset counts so that only genes represented in the other two objects are there:
length(intersect(rownames(tenx_5k_counts), rownames(mutant_counts_for_integration)))
[1] 5018

IMPORTANT - this next step is different to GCSKO_merge as it subsets the smart-seq2 data into wild-type only.

## subset wt on ss2 data:
ss2_wt_cells <- rownames(GCSKO_mutants@meta.data[GCSKO_mutants@meta.data$genotype == "WT", ])
GCSKO_mutants_wtonly <- subset(GCSKO_mutants, cells = ss2_wt_cells)

create list and normalise:

## make list
tenx.justwt.list <- list(tenx_5k_counts_to_integrate, GCSKO_mutants_wtonly)

## prepare data
for (i in 1:length(tenx.justwt.list)) {
    tenx.justwt.list[[i]] <- NormalizeData(tenx.justwt.list[[i]], verbose = FALSE)
    tenx.justwt.list[[i]] <- FindVariableFeatures(tenx.justwt.list[[i]], selection.method = "vst", 
        nfeatures = 2000, verbose = FALSE)
    all.genes <- rownames(tenx.justwt.list[[i]])
    tenx.justwt.list[[i]] <- ScaleData(tenx.justwt.list[[i]], features = all.genes)
}

Integrate objects

## Find anchors
tenx.justwt.anchors <- FindIntegrationAnchors(object.list = tenx.justwt.list, dims = 1:21, verbose = FALSE)

## Integrate data
tenx.justwt.integrated <- IntegrateData(anchorset = tenx.justwt.anchors, dims = 1:21, verbose = FALSE, features.to.integrate = genes_in_tenx_dataset)

4. Dimensionality reduction

PCA

Optimised UMAP

After optimisation, the following UMAP can be calculated:

## Run optimised UMAP
tenx.justwt.integrated <- RunUMAP(tenx.justwt.integrated, reduction = "pca", dims = 1:10, n.neighbors = 50, seed.use = 1234, min.dist = 0.4, repulsion.strength = 0.03, local.connectivity = 150)

Make final plots:


## split seurat object up
ob.list <- SplitObject(tenx.justwt.integrated, split.by = "experiment")

## make plots for each object
plot.list <- lapply(X = ob.list, FUN = function(x) {
    DimPlot(x, dims = c(1,2), pt.size = 1) + theme(legend.position="bottom")
})

composition_umap_10x <- plot.list$`tenx_5k` + 
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(45, "#999999"))) +
  labs(title = paste("10x (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap_ss2 <- plot.list$mutants +
  coord_fixed() +
  theme_void() +
  scale_color_manual(values=c(replicate(46, "#999999"))) +
  labs(title = paste("Smart-seq2 (wild-type)")) +
  theme(legend.position = "none", plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold"))

composition_umap <- composition_umap_10x + composition_umap_ss2 

composition_umap

save

ggsave("../images_to_export/composition_umap.png", plot = composition_umap, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)
## make plots
## hoo dataset correlation
UMAP_hoo <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman.", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("Hoo Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(12))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## ap2g timecourse in this paper correlation
UMAP_kasia <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "Prediction.Spearman._Kasia", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("AP2G Timecourse Predicted Timepoint")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_colour_manual(values = inferno(10))  +
  labs(colour = "hour") +
  theme(legend.position = "bottom", legend.title=element_text(size=10))

## combine
umap_bulk <- wrap_plots(UMAP_hoo, UMAP_kasia, ncol = 2)

## print
umap_bulk

MCA Mapping

Build the index

## load in mca data
counts <- read.csv("../data/Reference/scmap/allpb10x_counts.csv", row.names = 1)
pheno <- read.csv("../data/Reference/scmap/allpb10x_pheno.csv")

## change dash
rownames(counts) <- gsub("_", "-", rownames(counts))

## load MCA pal
mca_colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="darkgrey")

## plot
ggplot(pheno, aes(x=PC2_3d, y = PC3_3d, colour=absclust3)) + 
  geom_point() +
  theme_classic() +
  scale_color_manual(values = mca_colors, labels = (c("0 - early troph", "1 - mid troph","2 - late ring", "3 - late troph","4 - early schizont", "5 - late schizont", "6 - early ring","7 - mid schizont", "female", "male", "unassigned")))

###Making an ortholog reference index

## load required libraries
library(scmap)
Creating a generic function for ‘toJSON’ from package ‘jsonlite’ in package ‘googleVis’
library(SingleCellExperiment)
Loading required package: SummarizedExperiment
Loading required package: GenomicRanges
Loading required package: stats4
Loading required package: BiocGenerics
Loading required package: parallel

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:parallel’:

    clusterApply, clusterApplyLB, clusterCall, clusterEvalQ, clusterExport, clusterMap, parApply,
    parCapply, parLapply, parLapplyLB, parRapply, parSapply, parSapplyLB

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colnames, dirname, do.call,
    duplicated, eval, evalq, Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map,
    mapply, match, mget, order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind,
    Reduce, rownames, sapply, setdiff, sort, table, tapply, union, unique, unsplit, which,
    which.max, which.min

Loading required package: S4Vectors

Attaching package: ‘S4Vectors’

The following object is masked from ‘package:base’:

    expand.grid

Loading required package: IRanges
Loading required package: GenomeInfoDb
Loading required package: Biobase
Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor,
    see 'citation("Biobase")', and for packages 'citation("pkgname")'.

Loading required package: DelayedArray
Loading required package: matrixStats

Attaching package: ‘matrixStats’

The following objects are masked from ‘package:Biobase’:

    anyMissing, rowMedians


Attaching package: ‘DelayedArray’

The following objects are masked from ‘package:matrixStats’:

    colMaxs, colMins, colRanges, rowMaxs, rowMins, rowRanges

The following objects are masked from ‘package:base’:

    aperm, apply, rowsum


Attaching package: ‘SummarizedExperiment’

The following object is masked from ‘package:Seurat’:

    Assays
#prep the SCE, if was originally a Suerat object need the dfs to be regular matrices
#pb_filtered_sce_orth <- pb_filtered_sce_orth[, colData(pb_filtered_sce_orth)$absclust3 != "8"]
#sce <- pb_filtered_sce_orth
#pca <- plotPCA(sce)
#pcs <- pca$data
#table(rownames(pcs)==colnames(sce))
#colData(sce) <- cbind(colData(sce), pcs)
#rowData(sce)$feature_symbol <- rowData(sce)$gene
sce <- SingleCellExperiment(list(counts=counts),
    colData=DataFrame(label=pheno),
    rowData=DataFrame(feature_symbol=rownames(counts)))
sce
class: SingleCellExperiment 
dim: 4890 4884 
metadata(0):
assays(1): counts
rownames(4890): PBANKA-0000301 PBANKA-0000600 ... PBANKA-MIT0350 PBANKA-MIT0360
rowData names(1): feature_symbol
colnames(4884): AAACCTGAGCACCGTC AAACCTGAGCGCTTAT ... AGCTTGACAATAGAGT CCGGGATCACGTTGGC
colData names(21): label.X label.sample_id ... label.PC2_3d label.PC3_3d
reducedDimNames(0):
altExpNames(0):
counts_1 <- assay(sce, "counts")
libsizes <- colSums(counts_1)
size.factors <- libsizes/mean(libsizes)
logcounts(sce) <- log2(t(t(counts_1)/size.factors) + 1)
#counts(sce) <- as.matrix(counts(sce))
#logcounts(sce) <- as.matrix(logcounts(sce))
# remove features with duplicated names
sce <- sce[!duplicated(rownames(sce)), ]

#build scmap-cell reference index, save this rds
sce <- selectFeatures(sce, suppress_plot = FALSE, n_features = 500)

table(rowData(sce)$scmap_features)

FALSE  TRUE 
 4390   500 
set.seed(1)
sce <- indexCell(sce)
Parameter M was not provided, will use M = n_features / 10 (if n_features <= 1000), where n_features is the number of selected features, and M = 100 otherwise.
Parameter k was not provided, will use k = sqrt(number_of_cells)
names(metadata(sce)$scmap_cell_index)
[1] "subcentroids" "subclusters" 
length(metadata(sce)$scmap_cell_index$subcentroids)
[1] 50
dim(metadata(sce)$scmap_cell_index$subcentroids[[1]])
[1] 10 69
metadata(sce)$scmap_cell_index$subcentroids[[1]][,1:5]
                         1           2          3           4           5
PBANKA-0100021 0.000000000 0.002174527 0.00000000 0.000000000 0.001882238
PBANKA-0100400 0.674777171 0.000000000 0.71839411 0.000000000 0.000000000
PBANKA-0100700 0.000000000 0.000000000 0.06346152 0.000000000 0.003406199
PBANKA-0100900 0.026157737 0.000000000 0.03578261 0.000000000 0.439794449
PBANKA-0102700 0.000000000 0.000000000 0.00000000 0.007797631 0.010978344
PBANKA-0103200 0.000000000 0.000000000 0.00000000 0.000000000 0.000000000
PBANKA-0105100 0.000000000 0.000000000 0.00000000 0.000000000 0.000000000
PBANKA-0107300 0.007199727 0.999997636 0.65054584 0.999969598 0.898011255
PBANKA-0108800 0.734420349 0.000000000 0.23174764 0.000000000 0.004578116
PBANKA-0109900 0.067575567 0.000000000 0.04105225 0.000000000 0.000000000
dim(metadata(sce)$scmap_cell_index$subclusters)
[1]   50 4884
#saveRDS(pb_filtered_sce_orth, file="pb_filtered_sce_orthindex_20181109.rds")

Map to the index

## convert seurat object above into sce for this
pf_field_counts <- as.matrix(tenx.justwt.integrated@assays$RNA@data)
pf_field_pheno <- tenx.justwt.integrated@meta.data

#prep the SCE, if was originally a Suerat object need the dfs to be regular matrices
#pb_filtered_sce_orth <- pb_filtered_sce_orth[, colData(pb_filtered_sce_orth)$absclust3 != "8"]
#sce <- pb_filtered_sce_orth
#pca <- plotPCA(sce)
#pcs <- pca$data
#table(rownames(pcs)==colnames(sce))
#colData(sce) <- cbind(colData(sce), pcs)
#rowData(sce)$feature_symbol <- rowData(sce)$gene
pf_live_field.sce.orth <- SingleCellExperiment(list(counts=pf_field_counts),
    colData=DataFrame(label=pf_field_pheno),
    rowData=DataFrame(feature_symbol=rownames(pf_field_counts)))
pf_live_field.sce.orth
class: SingleCellExperiment 
dim: 5098 6880 
metadata(0):
assays(1): counts
rownames(5098): PBANKA-0000101 PBANKA-0000301 ... PBANKA-MIT0360 PBANKA-MIT0370
rowData names(1): feature_symbol
colnames(6880): AAACCTGGTAAGGGCT AAACCTGGTGCACTTA ... SC25027_8_95 SC25027_8_96
colData names(126): label.orig.ident label.nCount_RNA ... label.pt_id_cols
  label.seurat_clusters_dot_plotting
reducedDimNames(0):
altExpNames(0):
counts_1 <- assay(pf_live_field.sce.orth, "counts")
libsizes <- colSums(counts_1)
size.factors <- libsizes/mean(libsizes)
logcounts(pf_live_field.sce.orth) <- log2(t(t(counts_1)/size.factors) + 1)


#Project query data set onto cell index
scmapCell_results <- scmapCell(
  pf_live_field.sce.orth, 
  list(mca = metadata(sce)$scmap_cell_index
  )
)

##Look into the results
# For each dataset there are two matricies. cells matrix contains the top 10 (scmap default) cell IDs of the cells of the reference dataset that a given cell of the projection dataset is closest to:
#   
#   Give assignments in two ways:
#   1. Take the top cell assignment abs clust, if cosine similarity is less than 0.4 (or adjust if needed) mark as unassigned
# 2. For the top 3 nearest neighbors, get a mean of the PCA coordinates and snap to the nearest cell of those coordinates. If any of the top three cells are sim below 0.4 then mark as unassigned.


##Top cell assignment method
scmapCell_results$mca$cells[, 1:3]
      AAACCTGGTAAGGGCT AAACCTGGTGCACTTA AAACGGGTCGTCCAGG
 [1,]             1591             2340             2220
 [2,]             2310             2185             2122
 [3,]             4699             2242             2350
 [4,]             2137             1591             2242
 [5,]             2121             2430             1653
 [6,]             2092             2108             2457
 [7,]             1091             1094             2175
 [8,]             4680             2090             2170
 [9,]             2226             4122             2365
[10,]             2136             2226             2226
getcells <- scmapCell_results$mca$cells[1, ]
cdsce <- colData(sce)[getcells, ]
topsim <- scmapCell_results$mca$similarities[1, ]

pf_live_field.sce.orth$topcell <- cdsce$label.sample_id
pf_live_field.sce.orth$topcell_ac <- cdsce$label.absclust3
pf_live_field.sce.orth$indexPC1 <- cdsce$label.PC1
pf_live_field.sce.orth$indexPC2 <- cdsce$label.PC2
#pf_live_field.sce.orth$pbpt <- cdsce$pseudotime
#pf_live_field.sce.orth$pbbulk <- cdsce$bulk
pf_live_field.sce.orth$topcell_sp <- pf_live_field.sce.orth$topcell_ac
pf_live_field.sce.orth$topsim <- topsim
pf_live_field.sce.orth$topcell_sp[pf_live_field.sce.orth$topsim < 0.3] <- "unassigned"
table(pf_live_field.sce.orth$topcell_sp)

   0    1    2    3    4    5    6    7    F    M 
1766  534 3478  123   73   71  103   37  353  342 

add these metrics back into the object

## add the meta data from scmap to the object
# live
## extract
df_plot_live <- data.frame(topcell_sp = colData(pf_live_field.sce.orth)$topcell_sp, topsim = colData(pf_live_field.sce.orth)$topsim, row.names = rownames(colData(pf_live_field.sce.orth)))
## add to object
tenx.justwt.integrated <- AddMetaData(
  object = tenx.justwt.integrated,
  metadata = df_plot_live,
  col.name = c('mca_topcell_sp', 'mca_topsim')
)

## need to fix the NA in topcell_sp
# Un-factorize (as.numeric can be use for numeric values)
#              (as.vector  can be use for objects - not tested)
tenx.justwt.integrated@meta.data$mca_topcell_sp <- as.character(tenx.justwt.integrated@meta.data$mca_topcell_sp)
## add unassigned
tenx.justwt.integrated@meta.data$mca_topcell_sp[is.na(tenx.justwt.integrated@meta.data$mca_topcell_sp)] <- "unassigned"
# Re-factorize with the as.factor function or simple factor(fixed$Type)
tenx.justwt.integrated@meta.data$mca_topcell_sp <- as.factor(tenx.justwt.integrated@meta.data$mca_topcell_sp)
## check
table(tenx.justwt.integrated@meta.data$mca_topcell_sp)

   0    1    2    3    4    5    6    7    F    M 
1766  534 3478  123   73   71  103   37  353  342 
## reorder levels
tenx.justwt.integrated@meta.data$mca_topcell_sp <- factor(tenx.justwt.integrated@meta.data$mca_topcell_sp, levels = rev(c("M", "F", "5", "7", "4", "3", "1", "0", "2", "6")))

UMAP_mca <- DimPlot(tenx.justwt.integrated, pt.size = 0.1, group.by = "mca_topcell_sp", dims = c(1,2)) +
  coord_fixed() + 
  theme_void() +
  labs(title = paste("MCA Predicted Cell Type"), colour = "MCA Cell Type") + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) +
  scale_color_manual(values = mca_colors, labels = (c("6 - early ring", "2 - late ring", "0 - early troph", "1 - mid troph", "3 - late troph", "4 - early schizont", "7 - mid schizont", "5 - late schizont", "female", "male"))) +
  theme(legend.position = "right", legend.title=element_text(size=15))

UMAP_mca

save

ggsave("../images_to_export/UMAP_mca.png", plot = UMAP_mca, device = "png", path = NULL, scale = 1, width = 15, height = 15, units = "cm", dpi = 300, limitsize = TRUE)

5. Clustering

Generate clusters

## generate new clusters at low resolution
tenx.justwt.integrated <- FindNeighbors(tenx.justwt.integrated, dims = 1:19, reduction = "pca")
tenx.justwt.integrated <- FindClusters(tenx.justwt.integrated, resolution = 2, random.seed = 42, algorithm = 2)

visualise clusters

DimPlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE, repel = FALSE, label = TRUE)

Make individual plots highlighting where cells in each cluster fall

plot

## this function writes the next bit of code for you
## put it into the console and paste the response
#ploty <- c()
#for(i in seq_along(levels(tenx.justwt.integrated@meta.data$seurat_clusters))){
#  ploty <- paste0(ploty, "list_UMAPs_by_cluster[[", i, "]]", " + ")
#}

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Find Markers

markers_annotated <- merge(pb.markers, gene_annotations,  by.x = "gene", by.y = "Gene.ID", all = FALSE)
View(markers_annotated)
markers_annotated <- merge(pb.markers, gene_annotations,  by.x = "gene", by.y = "Gene.ID", all = FALSE)
View(markers_annotated)
markers_subset <- pb.markers %>% group_by(cluster) %>% top_n(n = 20, wt = avg_logFC)
markers_subset_annotated <- merge(markers_subset, gene_annotations,  by.x = "gene", by.y = "Gene.ID", all = FALSE)
markers_subset_annotated
View(markers_subset_annotated)
View(markers_annotated_mutant <- markers_annotated[which(markers_annotated$gene %in% list_of_mutant_genes), ])

visualise markers

## get the top 10 for each cluster
top10 <- pb.markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_logFC)

## scale data is missing - but original dfs have scale.data
# df_scaled <- as.matrix(transform(merge(as.data.frame(tenx.justwt.list[[1]]@assays$RNA@scale.data), as.data.frame(tenx.justwt.list[[2]]@assays$RNA@scale.data), by = 0, all=FALSE), row.names=Row.names, Row.names=NULL))
# tenx.justwt.integrated@assays$RNA@scale.data <- df_scaled

## scale data in RNA slot
all.genes <- rownames(tenx.justwt.integrated)
tenx.justwt.integrated <- ScaleData(tenx.justwt.integrated, vars.to.regress = 'experiment', features = all.genes)

## heatmap
DoHeatmap(tenx.justwt.integrated, features = top10$gene) + NoLegend()

6. Define Cluster Identities

Downsampling

# ## check number of cells in each cluster
# df_clusters <- as.data.frame(table(tenx.justwt.integrated@meta.data$integrated_snn_res.2))
# plot(df_clusters)
# 
# ## downsample using appropriate metrics
# tenx.justwt.integrated.downsampled <- subset(tenx.justwt.integrated, downsample = 100)
#   
# ## inspect plot
# FeaturePlot(tenx.justwt.integrated.downsampled, features = "PBANKA-1437500", coord.fixed = TRUE, dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
#   theme_void() + 
#   labs(title = paste("AP2G (Commitment)")) + 
#   theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
#   scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

Marker Genes

useful tools for all plots

## define male and female symbol
female_symbol <- intToUtf8(9792)
male_symbol <- intToUtf8(9794)

## define colour pal
marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

Expression - cutoffs - purple


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1319500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ccp2)~(Female))) + 
                          theme(plot.title = element_text(hjust = 0.5), 
                                legend.text = element_text(size = 5), 
                                text=element_text(size=6.0), 
                                plot.margin = unit(c(0, 0, 0, 0), "cm")
                                ) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, 
                                    features = "PBANKA-0416100", 
                                    coord.fixed = TRUE, 
                                    min.cutoff = "q05", 
                                    max.cutoff = "q95", 
                                    dims = c(1,2), 
                                    reduction = "umap", 
                                    pt.size = 0.5, 
                                    order = TRUE, 
                                    slot = 'scale.data') +
                        coord_fixed() + 
                        theme_void() + 
                        labs(title = expression(italic(mg1)~(Male))) + 
                        theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                        scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1437500", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(ap2g)~(Commitment))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0831000", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp1)~(Schizont))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1102200", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE, 
                                     slot = 'scale.data') + 
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(msp8)~(Asexual))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-1101300", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(SBP1)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0722600", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(fam-b2)~(Ring))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_ORC1 <- FeaturePlot(tenx.justwt.integrated, 
                                     features = "PBANKA-0602000", 
                                     coord.fixed = TRUE, 
                                     min.cutoff = "q05", 
                                     max.cutoff = "q95", 
                                     dims = c(1,2), 
                                     reduction = "umap", 
                                     pt.size = 0.5, 
                                     order = TRUE,
                                     slot = 'scale.data') +
                          coord_fixed() + 
                          theme_void() + 
                          labs(title = expression(italic(orc1)~(DNA~replication))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_CDPK5 <- FeaturePlot(tenx.justwt.integrated, 
                                      features = "PBANKA-1351500", 
                                      coord.fixed = TRUE, 
                                      min.cutoff = "q05", 
                                      max.cutoff = "q95", 
                                      dims = c(1,2), 
                                      reduction = "umap", 
                                      pt.size = 0.5, 
                                      order = TRUE, 
                                      slot = 'scale.data') +
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(cdpk5)~(Schizont))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

marker_gene_plot_MCM4 <- FeaturePlot(tenx.justwt.integrated, 
                                      features = "PBANKA-1415600", 
                                      coord.fixed = TRUE, 
                                      min.cutoff = "q05", 
                                      max.cutoff = "q95", 
                                      dims = c(1,2), 
                                      reduction = "umap", 
                                      pt.size = 0.5, 
                                      order = TRUE, 
                                      slot = 'scale.data') +
                          coord_fixed() +
                          theme_void() + 
                          labs(title = expression(italic(mcm4)~(DNA~replication))) + 
                          theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 5), text=element_text(size=6.0), plot.margin = unit(c(0, 0, 0, 0), "cm")) + 
                          scale_color_continuous_sequential(palette = "Purples 2", labels = number_format(accuracy = 0.1)) +
                          guides(colour = guide_colourbar(barwidth = 0.3, barheight = 3.0, title = ""))

# + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)

marker_gene_plot_all

Mutant Genes

Expression - with cutoffs

ggsave("../images_to_export/ALL_CELLS_wt_gene_expression.png", plot = mutant_expression_composite, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

save

ggsave("../images_to_export/ALL_CELLS_wt_gene_expression.png", plot = mutant_expression_composite, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE, min.cutoff = "q10", max.cutoff = "q90", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

7. Pseudotime on all cells

Pseudotime calculation

## extract data from Seurat
seurat.object.all <- tenx.justwt.integrated
# counts
data <- as(as.matrix(GetAssayData(seurat.object.all, assay = "integrated", slot = "data")), 'sparseMatrix')
# meta data
pd <- data.frame(seurat.object.all@meta.data)

## keep only the columns that are relevant
#pData <- pd %>% select(orig.ident, nCount_RNA, nFeature_RNA)
## add gene short name
fData <- data.frame(gene_short_name = row.names(data), row.names = row.names(data))

## Construct monocle cds
monocle.object.all <- new_cell_data_set(expression_data = data, cell_metadata = pd, gene_metadata = fData)
## preprocess
monocle.object.all = preprocess_cds(monocle.object.all, num_dim = 100, norm_method = "none")
## plot variance explained plot
#plot_pc_variance_explained(monocle.object.all)
## make monocle UMAP
#monocle.object.all = reduce_dimension(monocle.object.all, reduction_method = "UMAP", preprocess_method = "PCA", umap.metric = "euclidean", umap.n_neighbors = 20, umap.min_dist = 0.5, verbose = FALSE)
#plot_cells(monocle.object.all)

## add UMAP from Seurat
monocle.object.all@int_colData@listData$reducedDims@listData[["UMAP"]] <-seurat.object.all@reductions[["umap"]]@cell.embeddings 
plot_cells(monocle.object.all)

## cluster
monocle.object.all = cluster_cells(monocle.object.all)

## plot clusters
plot_cells(monocle.object.all, color_cells_by="partition", group_cells_by="partition",  x = 1, y = 2)

## reduce partitions to 1
monocle.object.all@clusters$UMAP$partitions[monocle.object.all@clusters$UMAP$partitions == "2"] <- "1"

#map pseudotime
monocle.object.all = learn_graph(monocle.object.all, learn_graph_control=list(ncenter=550, minimal_branch_len = 15), use_partition = FALSE)

plot_cells(monocle.object.all, color_cells_by="partition", group_cells_by="partition",  x = 1, y = 2)

## a helper function to identify the root principal points:
## make cluster 2 the root
# get_earliest_principal_node <- function(cds, time_bin="7"){
#   cell_ids <- which(colData(cds)[, "seurat_clusters"] == time_bin)
#   closest_vertex <-
#   cds@principal_graph_aux[["UMAP"]]$pr_graph_cell_proj_closest_vertex
#   closest_vertex <- as.matrix(closest_vertex[colnames(cds), ])
#   root_pr_nodes <-
#   igraph::V(principal_graph(cds)[["UMAP"]])$name[as.numeric(names
#   (which.max(table(closest_vertex[cell_ids,]))))]
#   
#   root_pr_nodes
# }

## calculate pseudotime
#monocle.object.all = order_cells(monocle.object.all, root_pr_nodes=get_earliest_principal_node(monocle.object.all))
monocle.object.all = order_cells(monocle.object.all)
## used 5 points at the beginning


## plot
umap_pt <- plot_cells(monocle.object.all, color_cells_by = "pseudotime", label_cell_groups=FALSE, cell_size = 1, x = 1, y = 2, label_branch_points=FALSE, label_leaves=FALSE, label_groups_by_cluster=FALSE, label_roots = FALSE) +
  coord_fixed() +
  theme_void() +
  labs(title = "") +
  theme(plot.title = element_text(hjust = 0.5, size=20), legend.position="bottom", legend.title=element_text (size=20), legend.text=element_text(size=20)) + 
  guides(colour = guide_colourbar(barwidth = 10, barheight = 2, title = "Pseudotime"))

## view plot
umap_pt

## help was obtained from here
## https://github.com/satijalab/seurat/issues/1658

save

ggsave("../images_to_export/UMAP_pt_wt.png", plot = umap_pt, device = "png", path = NULL, scale = 1, width = 20, height = 20, units = "cm", dpi = 300, limitsize = TRUE)

gganimnate GIF of pseuodtime

Select appropriate cells

plot <- DimPlot(tenx.justwt.integrated, label = FALSE, repel = TRUE, pt.size = 0.1, dims = c(1,2), reduction = "umap")
HoverLocator(plot, information = FetchData(object = tenx.justwt.integrated, vars = 'monocle_sex'))
the condition has length > 1 and only the first element will be usedthe condition has length > 1 and only the first element will be used`error_y.color` does not currently support multiple values.`error_x.color` does not currently support multiple values.`line.color` does not currently support multiple values.The titlefont attribute is deprecated. Use title = list(font = ...) instead.the condition has length > 1 and only the first element will be usedthe condition has length > 1 and only the first element will be used`error_y.color` does not currently support multiple values.`error_x.color` does not currently support multiple values.`line.color` does not currently support multiple values.The titlefont attribute is deprecated. Use title = list(font = ...) instead.
cells_to_remove <- c("SC26779_8_280", "CTGGTCTAGCAGATCG")
#install.packages("gganimate")
library(gganimate)
#install.packages("gifski")
#install.packages("av")
#library(gifski)
#library(av)

## make dataframe for plotting
## extract data for GGplot version of this
df_animation <- as.data.frame(monocle.object.all@int_colData@listData$reducedDims@listData[["UMAP"]])
## add pt to this data frame:
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))
df_animation <- merge(df_animation, pt_values, by="row.names") 
rownames(df_animation) <- df_animation$Row.names
colnames(df_animation)[4] <- "pt"

## make the static plot
p <- ggplot(df_animation, aes(x = UMAP_1, y = UMAP_2, colour = pt)) +
  geom_point() +
  scale_colour_viridis_c(option = "plasma") +
  coord_fixed() +
  theme_void() +
  theme(legend.position = "none")
## view plot
plot(p)

## make animated plot
## make a category for animation
#df_animation$group <- cut(df_animation$pt, 15)

anim <- p +
  transition_time(pt) +
  shadow_mark()

animate(anim, height = 3, width = 3, units = "in", res = 150, bg = 'transparent')

## to change the resolution - https://stackoverflow.com/questions/49058567/define-size-for-gif-created-by-gganimate-change-dimension-resolution 

Save animation

anim_save("animated_UMAP_transparent_bg_wt.gif", path = "../images_to_export/")
## extract pt values
pt_values <- as.data.frame(pseudotime(monocle.object.all, reduction_method = "UMAP"))

tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, pt_values, "old_pt_values")

## make dataframe for plotting
## extract data for GGplot version of this
df_animation <- as.data.frame(tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings)
## add pt to this data frame:
pt_values <- as.data.frame(tenx.justwt.integrated@meta.data[ ,c("old_pt_values", "pt_id_cols"), drop = FALSE])
df_animation <- merge(df_animation, pt_values, by="row.names") 
rownames(df_animation) <- df_animation$Row.names
colnames(df_animation)[4] <- "pt"
## remove outlier cells
df_animation <- df_animation[which(df_animation$Row.names %ni% cells_to_remove), ]

#df_animation <- df_animation[order(df_animation$pt, decreasing = TRUE), ]

## make a category for animation
#df_animation$group <- as.numeric(cut(df_animation$pt, 10, include.lowest = TRUE, labels = c(1:10)))

## make the static plot
p <- ggplot(df_animation, aes(x = UMAP_1, y = UMAP_2)) +
  geom_point(col = df_animation$pt_id_cols) +
  #scale_colour_viridis_c(option = "plasma") +
  coord_fixed() +
  theme_void() +
  theme(legend.position = "none") +
  view_static()
## view plot
plot(p)

## make animated plot


anim <- p +
  transition_time(pt) +
  shadow_mark() +
  #shadow_wake(wake_length = 0.99) #+
  enter_fade()

animate(anim, 
        height = 3, 
        width = 3, 
        units = "in", 
        res = 300, 
        bg = 'white', 
        #duration = 6, 
        fps = 20, 
        device = "png",
        #ref_frame = 1
        end_pause = 10
        )

Frame 1 (1%)
Frame 2 (2%)
Frame 3 (3%)
Frame 4 (4%)
Frame 5 (5%)
Frame 6 (6%)
Frame 7 (7%)
Frame 8 (8%)
Frame 9 (9%)
Frame 10 (10%)
Frame 11 (11%)
Frame 12 (12%)
Frame 13 (13%)
Frame 14 (14%)
Frame 15 (15%)
Frame 16 (16%)
Frame 17 (17%)
Frame 18 (18%)
Frame 19 (19%)
Frame 20 (20%)
Frame 21 (21%)
Frame 22 (22%)
Frame 23 (23%)
Frame 24 (24%)
Frame 25 (25%)
Frame 26 (26%)
Frame 27 (27%)
Frame 28 (28%)
Frame 29 (29%)
Frame 30 (30%)
Frame 31 (31%)
Frame 32 (32%)
Frame 33 (33%)
Frame 34 (34%)
Frame 35 (35%)
Frame 36 (36%)
Frame 37 (37%)
Frame 38 (38%)
Frame 39 (39%)
Frame 40 (40%)
Frame 41 (41%)
Frame 42 (42%)
Frame 43 (43%)
Frame 44 (44%)
Frame 45 (45%)
Frame 46 (46%)
Frame 47 (47%)
Frame 48 (48%)
Frame 49 (49%)
Frame 50 (50%)
Frame 51 (51%)
Frame 52 (52%)
Frame 53 (53%)
Frame 54 (54%)
Frame 55 (55%)
Frame 56 (56%)
Frame 57 (57%)
Frame 58 (58%)
Frame 59 (59%)
Frame 60 (60%)
Frame 61 (61%)
Frame 62 (62%)
Frame 63 (63%)
Frame 64 (64%)
Frame 65 (65%)
Frame 66 (66%)
Frame 67 (67%)
Frame 68 (68%)
Frame 69 (69%)
Frame 70 (70%)
Frame 71 (71%)
Frame 72 (72%)
Frame 73 (73%)
Frame 74 (74%)
Frame 75 (75%)
Frame 76 (76%)
Frame 77 (77%)
Frame 78 (78%)
Frame 79 (79%)
Frame 80 (80%)
Frame 81 (81%)
Frame 82 (82%)
Frame 83 (83%)
Frame 84 (84%)
Frame 85 (85%)
Frame 86 (86%)
Frame 87 (87%)
Frame 88 (88%)
Frame 89 (89%)
Frame 90 (90%)
Frame 91 (91%)
Frame 92 (92%)
Frame 93 (93%)
Frame 94 (94%)
Frame 95 (95%)
Frame 96 (96%)
Frame 97 (97%)
Frame 98 (98%)
Frame 99 (99%)
Frame 100 (100%)
Finalizing encoding... done!

Define cell identities with branches

Define identities of cells

male

monocle.object_male <- choose_graph_segments(monocle.object.all)

female

monocle.object_female <- choose_graph_segments(monocle.object.all)

bipotential

monocle.object_bipot <- choose_graph_segments(monocle.object.all)

asexual (pre-branch)

monocle.object_asex_pre <- choose_graph_segments(monocle.object.all)

asexual fate

monocle.object_asex_fate <- choose_graph_segments(monocle.object.all)

check

df_freq <- data.frame(table(c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex_pre), colnames(monocle.object_asex_fate))))
paste("number of cells in seurat object is", length(colnames(monocle.object.all)), ". The number of cells selected here with an identitity is", dim(df_freq)[1])
df_freq <- df_freq[df_freq$Freq > 1, ]
df_freq

Inspect where these missing cells are:

# '%ni%' <- Negate('%in%')
# 
# not_assigned_cells <- colnames(monocle.object.all)[colnames(monocle.object.all) %ni% c(colnames(monocle.object_male), colnames(monocle.object_female), colnames(monocle.object_bipot), colnames(monocle.object_asex), colnames(monocle.object_asex_fate))]
# 
# DimPlot(seurat.object, repel = TRUE, label.size = 5, pt.size = 0.5, cells.highlight = not_assigned_cells, dims = c(2,1), reduction = "DIM_UMAP") +
#   coord_fixed() + 
#   scale_color_manual(values=c("#000000", "#f54e1e"))
## create annotation dataframe from these results:
df_monocle_sexes <- rbind(data.frame("cell_name" = colnames(monocle.object_male), "sex" = rep("Male", length(colnames(monocle.object_male)))),
                          data.frame("cell_name" = colnames(monocle.object_female), "sex" = rep("Female", length(colnames(monocle.object_female)))),
                          data.frame("cell_name" = colnames(monocle.object_bipot), "sex" = rep("Bipotential", length(colnames(monocle.object_bipot)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_pre), "sex" = rep("Asexual_Early", length(colnames(monocle.object_asex_pre)))),
                          data.frame("cell_name" = colnames(monocle.object_asex_fate), "sex" = rep("Asexual_Late", length(colnames(monocle.object_asex_fate))))
                          #data.frame("cell_name" = not_assigned_cells, "sex" = rep("Unassigned", length(not_assigned_cells)))
                          )

dim(df_monocle_sexes)

## order like the metadata
df_monocle_sexes <- df_monocle_sexes[match(rownames(monocle.object.all@colData), df_monocle_sexes$cell_name), ]

## add this back into the monocle object
monocle.object.all@colData$Sexes_monocle <- df_monocle_sexes$sex

## add this to the seurat object
rownames(df_monocle_sexes) <- df_monocle_sexes$cell_name
df_monocle_sexes_to_add_to_seurat <- df_monocle_sexes[,c("sex"), drop = FALSE]
tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, df_monocle_sexes_to_add_to_seurat, col.name = "monocle_sex")

pt vs. real time

gg <- ggplot(df_plotting, aes(as.factor(Prediction.Spearman.), fill = monocle_sex)) + geom_bar(stat = "count", position="fill")

gg

gg <- ggplot(df_plotting, aes(as.factor(Prediction.Spearman.), fill = monocle_sex)) + geom_bar(stat = "count", position="fill")

gg

8. Plots

make composite pseudotime/ID figure

# 1 = blue - "#0052c5"
# 2 = red - "#a52b1e"
# 3 = green - "#016c00"
# 4 = yellow - "#ffe400"
#pal_sex <- c("#0052c5","#ffe400", "#a52b1e", "#016c00")

## extract pseudotime numbers and identity of cells to a dataframe
df_pt_id <- tenx.justwt.integrated@meta.data[,c("old_pt_values", "monocle_sex")]

## inspect possible values
list_of_sexes <- names(table(df_pt_id$monocle_sex))

## make a new column
df_pt_id$colour <- NA

## make colour ramps
asex_ramp <- colorRampPalette(c("#D5E3F5", "#0052c5"))
male_ramp <- colorRampPalette(c("white", "yellow", "#016c00"))
female_ramp <- colorRampPalette(c("yellow", "#a52b1e"))
bipot_ramp <- colorRampPalette(c("white", "#ffe400"))

## re-classify the cells that are unassigned cells removed from sexual branch above:
#df_pt_id[which(rownames(df_pt_id) %in% remove_cells), ]$monocle_sex <- "Asexual"

## assign values to each cluster
## help here: https://stackoverflow.com/questions/9946630/colour-points-in-a-plot-differently-depending-on-a-vector-of-values 
df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$colour <- asex_ramp(100)[as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$old_pt_values,breaks = 100))]

df_pt_id[df_pt_id$monocle_sex == "Male", ]$colour <- male_ramp(100)[as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Male", ]$old_pt_values,breaks = 100))]

df_pt_id[df_pt_id$monocle_sex == "Female", ]$colour <- female_ramp(100)[as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Female", ]$old_pt_values,breaks = 100))]

df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$colour <- bipot_ramp(100)[as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$old_pt_values,breaks = 100))]

## check everything has a value
#table(is.na(df_pt_id$colour))

## make into a df
#df_pt_id <- df_pt_id[ ,"colour", drop = FALSE]

## add back to seurat object
df <- df_pt_id[ ,"colour", drop = FALSE]
tenx.justwt.integrated <- AddMetaData(tenx.justwt.integrated, df, "pt_id_cols")
rm(df)

## plot
## extract UMAP coords
df_umap_plot <- tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings
df_umap_plot <- merge(df_umap_plot, df_pt_id, by=0, all=TRUE)

## add tree
##The tree for monocle is located here:
# monocle.object@principal_graph_aux[["UMAP"]]$dp_mst 
ica_space_df <- t(monocle.object.all@principal_graph_aux[["UMAP"]]$dp_mst) %>%
      as.data.frame() %>%
      dplyr::select_(prin_graph_dim_1 = "UMAP_1", prin_graph_dim_2 = "UMAP_2") %>%
      dplyr::mutate(sample_name = rownames(.),
                    sample_state = rownames(.))

dp_mst <- monocle.object.all@principal_graph[["UMAP"]]

edge_df <- dp_mst %>%
      igraph::as_data_frame() %>%
      dplyr::select_(source = "from", target = "to") %>%
      dplyr::left_join(ica_space_df %>%
                         dplyr::select_(
                           source="sample_name",
                           source_prin_graph_dim_1="prin_graph_dim_1",
                           source_prin_graph_dim_2="prin_graph_dim_2"),
                       by = "source") %>%
      dplyr::left_join(ica_space_df %>%
                         dplyr::select_(
                           target="sample_name",
                           target_prin_graph_dim_1="prin_graph_dim_1",
                           target_prin_graph_dim_2="prin_graph_dim_2"),
                       by = "target")

## make ggplot
umap_id_pt <- ggplot(df_umap_plot, aes(x = UMAP_1, y = UMAP_2)) + 
                     geom_point(col = df_umap_plot$colour) +
                     theme_void() +
                     coord_fixed() +
                     geom_segment(aes_string(x="source_prin_graph_dim_1",
                                     y="source_prin_graph_dim_2",
                                     xend="target_prin_graph_dim_1",
                                     yend="target_prin_graph_dim_2"),
                          data=edge_df)

umap_id_pt

save

#ggsave("../images_to_export/umap_id_pt.png", plot = umap_id_pt, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)

cluster plot

### Prepare data

## extract df with cluster ID, 
df_pt_id <- tenx.justwt.integrated@meta.data[ ,"seurat_clusters", drop=FALSE]
## extract UMAP coords
df_plot <- tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings
df_plot <- merge(df_plot, df_pt_id, by=0, all=TRUE)
## add colour col
df_plot$colour <- df_plot$seurat_clusters
levels(df_plot$colour) <- list(print(asex_ramp(17)[1]) = "9", asex_ramp(17)[2]="4", 
                               asex_ramp(17)[3]="15", 
                                asex_ramp(17)[4] = "8", 
                                asex_ramp(17)[5]= "1",
                                asex_ramp(17)[6]=  "14", 
                                asex_ramp(17)[7] = "2", 
                                asex_ramp(17)[8] = "10",
                                asex_ramp(17)[9] = "3",
                                asex_ramp(17)[10] = "0",
                                asex_ramp(17)[11] = "6",
                                asex_ramp(17)[12] = "5",
                                asex_ramp(17)[13] = "7",
                                asex_ramp(17)[14] = "12",
                                asex_ramp(17)[15] = "18",
                                asex_ramp(17)[16] = "20",
                                asex_ramp(17)[17] = "23",
                                bipot_ramp(3)[2] = "11",
                                male_ramp(3)[2] = "16",
                                male_ramp(3)[3] = "13",
                                female_ramp(4)[2] = "21",
                                female_ramp(4)[3] = "22",
                                female_ramp(4)[4] = "19",
                                female_ramp(4)[4] = "17"
                                      )
## aabbreviate clusters
df_plot$cluster_names <- df_plot$seurat_clusters
levels(df_plot$cluster_names) <- list(A_1="9", 
                                      A_2="4", 
                                      A_3="15", 
                                      A_4 = "8", 
                                      A_5 = "1",
                                      A_6=  "14", 
                                      A_7 = "2", 
                                      A_8 = "10",
                                      A_9 = "3",
                                      A_10 = "0",
                                      A_11 = "6",
                                      A_12 = "5",
                                      A_13 = "7",
                                      A_14 = "12",
                                      A_15 = "18",
                                      A_16 = "20",
                                      A_17 = "23",
                                      B = "11",
                                      M_1 = "16",
                                      M_2 = "13",
                                      F_1 = "21",
                                      F_2 = "22",
                                      F_3 = "19",
                                      F_3 = "17"
                                      )

library(dplyr)
dat%>%
group_by(custid)%>% 
summarise(Mean=mean(value), Max=max(value), Min=min(value), Median=median(value), Std=sd(value))



## plot
umap_id <- ggplot(df_plot, aes(x = UMAP_1, y = UMAP_2)) + 
                     geom_point(col = df_plot$colour) +
                     theme_void() +
                     coord_fixed()

umap_id
ggsave("../images_to_export/umap_with_clusters.png", plot = umap_with_clusters, device = "png", path = NULL, scale = 1, width = 21, height = 29.5, units = "cm", dpi = 300, limitsize = TRUE)

save

ggsave("../images_to_export/umap_with_clusters.png", plot = umap_with_clusters, device = "png", path = NULL, scale = 1, width = 21, height = 29.5, units = "cm", dpi = 300, limitsize = TRUE)
## extract proportion of cells
library(plyr)
df_prop_comb <- as.data.frame(table(tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting, tenx.justwt.integrated@meta.data$experiment))
names(df_prop_comb) <- c("cluster", "experiment", "Freq")

## calcualte the percentage
df_prop_comb$pc <- NA
df_prop_comb[df_prop_comb$experiment == "mutants", ]$pc <- (df_prop_comb[df_prop_comb$experiment == "mutants", ]$Freq/sum(df_prop_comb[df_prop_comb$experiment == "mutants", ]$Freq))*100
df_prop_comb[df_prop_comb$experiment == "tenx_5k", ]$pc <- (df_prop_comb[df_prop_comb$experiment == "tenx_5k", ]$Freq/sum(df_prop_comb[df_prop_comb$experiment == "tenx_5k", ]$Freq))*100

## reorder levels in Var1 
#df_prop_comb$cluster <- factor(df_prop_comb$cluster, levels = c("unassigned", "M", "F", "5", "7", "4", "3", "1", "0", "2", "6"))

## then reorder by this so the cumsum will work below
df_prop_comb <- df_prop_comb[rev(order(df_prop_comb$experiment, df_prop_comb$cluster)),]

## Calculate the cumulative sum of len for each dose
df_cumsum <- ddply(df_prop_comb, "experiment", transform, label_ypos=cumsum(pc) - 0.5*pc)
head(df_cumsum)
# http://www.sthda.com/english/wiki/ggplot2-barplots-quick-start-guide-r-software-and-data-visualization

## reverse the levels in Var1
#df_cumsum$cluster <- factor(df_cumsum$cluster, levels = rev(c(levels(df_cumsum$cluster))))
#df_cumsum <- df_cumsum[c(match(df_cumsum$cluster[1:23], c(levels(df_cumsum$cluster))), match(df_cumsum$cluster[1:23], c(levels(df_cumsum$cluster))) + 23), ]

library(ggrepel)
library(ggpubr)
## make plot
plot_prop <- ggplot(data=df_cumsum, aes(x=experiment, y=pc, fill=cluster)) +
  geom_bar(stat="identity")+
  geom_label_repel(aes(label = Freq, y=label_ypos, fill = factor(cluster)), color = c(rep(c(rep(c("#ffffff"), 2), "#000000", "#ffffff", rep(c("#000000"), 2), rep(c("#ffffff"), 5), rep(c("#000000"), 12)), 2)), size = 3.5, show.legend = FALSE) +
  #geom_text(aes(y=label_ypos, label=Freq), vjust=0, color="black", size=3.5) +
  labs(fill = "Cell cluster", y= "Cell Proportions (%)", x = "Technology") +
  scale_fill_manual(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Progenitor", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3"), values = pal_plot) +
  theme_pubr() +
  theme(legend.text=element_text(size=10), legend.position="bottom") +
  scale_x_discrete(labels= rev(c("10x", "Smart-seq2"))) +
  coord_flip() +
  guides(fill=guide_legend(ncol=9))


plot_prop
ggsave("../images_to_export/WT_cell_type_proportions.png", plot = plot_prop, device = "png", path = NULL, scale = 1, width = 30, height = 9, units = "cm", dpi = 300, limitsize = TRUE)

dotplot

A dotplot allows us to look at the expression of multiple genes in a clearer way than succesive UMAP plots

### Data set-up

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0413400    GCSKO-10_820  MD3
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0102400         GCSKO-2  MD5 

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

# PBANKA-1437500 - AP2G - commitment
# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)

marker_genes_list <- c("PBANKA-1437500", "PBANKA-1319500", "PBANKA-0416100", "PBANKA-0831000", "PBANKA-1102200")
mutant_genes_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0413400", "PBANKA-0716500", "PBANKA-0102400",  "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

## these get defined later on, but are replicated above here for plotting
asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## copy the clusters so you don't permanently edit the master
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- tenx.justwt.integrated@meta.data$seurat_clusters

## reorder the levels so you can plot the cluters as you wish
my_levels <- c(asexual_early_clusters,asexual_late_clusters, bipotential_clusters, male_clusters, female_clusters)

## reorder the levels
tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting <- factor(x = tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting, levels = my_levels)

## rename clusters so that they are intuitive
# this trick is from here: http://www.cookbook-r.com/Manipulating_data/Renaming_levels_of_a_factor/
levels(tenx.justwt.integrated@meta.data$seurat_clusters_dot_plotting) <- list(Asexual_1="9", 
                                                                              Asexual_2="4", 
                                                                              Asexual_3="15", 
                                                                              Asexual_4 = "8", 
                                                                              Asexual_5 = "1",
                                                                              Asexual_6=  "14", 
                                                                              Asexual_7 = "2", 
                                                                              Asexual_8 = "10",
                                                                              Asexual_9 = "3",
                                                                              Asexual_10 = "0",
                                                                              Asexual_11 = "6",
                                                                              Asexual_12 = "5",
                                                                              Asexual_13 = "7",
                                                                              Asexual_14 = "12",
                                                                              Asexual_15 = "18",
                                                                              Asexual_16 = "20",
                                                                              Asexual_17 = "23",
                                                                              Progenitor = "11",
                                                                              Male_1 = "16",
                                                                              Male_2 = "13",
                                                                              Female_1 = "21",
                                                                              Female_2 = "22",
                                                                              Female_3 = "19",
                                                                              Female_3 = "17"
                                                                              )

### Annotation set-up

## extract pseudotime numbers and identity of cells to a dataframe
df_pt_id <- tenx.justwt.integrated@meta.data[,c("old_pt_values", "monocle_sex", "seurat_clusters_dot_plotting", "Prediction.Spearman.", "Prediction.Spearman._Kasia")]

## make a new column
df_pt_id$colour <- NA

## assign bins to each of the values
## help here: https://stackoverflow.com/questions/9946630/colour-points-in-a-plot-differently-depending-on-a-vector-of-values 
df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Asexual_Early" | df_pt_id$monocle_sex == "Asexual_Late", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Male", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Male", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Female", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Female", ]$old_pt_values,breaks = 100))

df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$colour <- as.numeric(cut(df_pt_id[df_pt_id$monocle_sex == "Bipotential", ]$old_pt_values,breaks = 100))

## make colour ramps
asex_ramp <- colorRampPalette(c("#D5E3F5", "#0052c5"))
male_ramp <- colorRampPalette(c("white", "yellow", "#016c00"))
female_ramp <- colorRampPalette(c("yellow", "#a52b1e"))
bipot_ramp <- colorRampPalette(c("white", "#ffe400"))

## assign values to each cluster
## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "colour"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
## BECAUSE we have ordered the clusters already, we can simply take the row index for this bit
df_annotation$colour <- NA
df_annotation[1:17, ]$colour <- asex_ramp(100)[df_annotation[1:17, ]$x]
df_annotation[18, ]$colour <- bipot_ramp(100)[df_annotation[18, ]$x]
df_annotation[19:20, ]$colour <- male_ramp(100)[df_annotation[19:20, ]$x]
df_annotation[21:23, ]$colour <- female_ramp(100)[df_annotation[21:23, ]$x]

## plot annotation 
## this really helped: https://www.biostars.org/p/396810/
h2 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h2 <- h2 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)
 
 h1 <- ggplot(df_annotation)+
  geom_point(mapping = aes(x = Group.1, y = 1),
            col = df_annotation$colour,
            size = 5)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     #legend <- plot_grid(get_legend(h2), get_legend(h1), ncol = 1)
 h1 <- h1 + theme(legend.position = "none")
 #   geom_point(col = df_umap_plot$colour)

 ## add predicted time point
 ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman."], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h3 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))#+
     #facet_grid(.~colour, scales = "free_x")
     legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")

  h3 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis(option = 'cividis')
 legend_h3 <- get_legend(h3)
 h3 <- h3 + theme(legend.position = "none")
 
 ## add kasia data
  ## take the mean of the bin
df_annotation <- aggregate(df_pt_id[, "Prediction.Spearman._Kasia"], list(df_pt_id$seurat_clusters_dot_plotting), mean)
df_annotation$colour <- NA
df_annotation$colour <- viridis(300)[(df_annotation$x)*10]

h4 <- ggplot(df_annotation)+
  geom_bar(mapping = aes(x = Group.1, y = 1), 
           stat = "identity",
           fill = df_annotation$colour,
           col = "#FFFFFF",
           width = 1)+
      theme_void()+
      theme(panel.spacing.x = unit(1, "mm"))+
     facet_grid(.~colour, scales = "free_x")
     legend <- plot_grid(get_legend(h4), ncol = 1)
    legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

 h4 <- ggplot(data = df_annotation, 
              mapping = aes(x = Group.1, fill=x)
              ) +
       geom_bar(col = "#FFFFFF", width = 1)+
       theme_void() +
       theme(panel.spacing.x = unit(1, "mm")) +
       scale_fill_viridis()
 legend_h4 <- get_legend(h4)
 h4 <- h4 + theme(legend.position = "none")

### Plot
dot_plot_markers <- DotPlot(tenx.justwt.integrated, 
                            features = c(marker_genes_list, rev(mutant_genes_list)), 
                            group.by = "seurat_clusters_dot_plotting", 
                            dot.min = 0.00001,
                            assay = 'RNA') +
  theme_classic() +
  coord_fixed() +
  coord_flip() +
  # change appearance and remove axis elements, and make room for arrows
  theme(axis.text.x = element_text(size=16, angle = 45, hjust=1,vjust=1, family = "Arial"), 
        axis.text.y = element_text(size=16, face="italic"), 
        text=element_text(size=16, family="Arial", colour="black"), 
        legend.position = "bottom", 
        legend.direction = "horizontal", 
        legend.box = "vertical", 
        plot.title = element_blank(), 
        plot.margin = unit(c(1,3,1,3), "lines"), 
        axis.line = element_blank(),
        panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
  #change the colours
  #scale_colour_viridis(option = "inferno", guide = "colourbar", na.value="white", begin = 0, end = 1, direction = 1) +
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## change x axis label
  # labs(x = "Marker Genes", y = "Cluster", title = "Expression of Marker Genes by Cluster") 
  labs(x = "", y = "", title = "") +
  ## add arrows
  #annotate("segment", x = 5.5, xend = 5.5, y = 21.5, yend = 25, colour = "green", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 16.5, yend = 21.5, colour = "red", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  #annotate("segment", x = 5.5, xend = 5.5, y = 0, yend = 15.5, colour = "grey", size=1, alpha=1, arrow=arrow(length=unit(0.30,"cm"), type = "closed")) +
  ## annotate asex
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate bipotential
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## annotate sexes
  geom_hline(aes(yintercept = (length(c(asexual_early_clusters, asexual_late_clusters, bipotential_clusters, male_clusters))+0.5)), size = 0.5, linetype= 'dashed') +
  ## change label on bottom of plot so we can indicate markers
  scale_x_discrete(labels = rev(c("gd1", "md1", "md2", "md3", "md4", "md5", "fd1", "fd2", "fd3", "fd4", "msp8", "msp1", "mg1", "ccp2", "ap2g"))) +
  ## change label on bottom of plot so we can indicate markers
  scale_y_discrete(labels = c("Asexual 1", "Asexual 2" , "Asexual 3", "Asexual 4", "Asexual 5", "Asexual 6", "Asexual 7", "Asexual 8",  "Asexual 9", "Asexual 10", "Asexual 11", "Asexual 12", "Asexual 13", "Asexual 14", "Asexual 15", "Asexual 16", "Asexual 17", "Progenitor", "Male 1", "Male 2", "Female 1", "Female 2", "Female 3")) +
  ## change name of legends
  guides(col=guide_colorbar(title = 'Scaled Average Expression'),
         size=guide_legend("% of cells expressing"))

## view
#print(dot_plot_markers)

plot <- plot_grid(h4, h3, h1, dot_plot_markers, align = "v", ncol = 1, axis = "tb", rel_heights = c(0.5, 0.5, 0.5, 18)) 

dot_plot <- plot_grid(plot, legend_h3, legend_h4, nrow = 1, rel_widths = c(10, 1.5, 1.5))

dot_plot

save

ggsave("../images_to_export/dot_plot_all.png", plot = dot_plot, device = "png", path = NULL, scale = 1, width = 29.7, height = 21, units = "cm", dpi = 300, limitsize = TRUE)

Make individual plots highlighting where cells in each cluster fall

plot

## this function writes the next bit of code for you
## put it into the console and paste the response
#ploty <- c()
#for(i in seq_along(levels(tenx.justwt.integrated@meta.data$seurat_clusters))){
#  ploty <- paste0(ploty, "list_UMAPs_by_cluster[[", i, "]]", " + ")
#}

## plot
composite_plot <- plot_grid(list_UMAPs_by_cluster[[1]], list_UMAPs_by_cluster[[2]], list_UMAPs_by_cluster[[3]], list_UMAPs_by_cluster[[4]], list_UMAPs_by_cluster[[5]], list_UMAPs_by_cluster[[6]], list_UMAPs_by_cluster[[7]], list_UMAPs_by_cluster[[8]], list_UMAPs_by_cluster[[9]], list_UMAPs_by_cluster[[10]], list_UMAPs_by_cluster[[11]], list_UMAPs_by_cluster[[12]], list_UMAPs_by_cluster[[13]], list_UMAPs_by_cluster[[14]], list_UMAPs_by_cluster[[15]], list_UMAPs_by_cluster[[16]], list_UMAPs_by_cluster[[17]], list_UMAPs_by_cluster[[18]], list_UMAPs_by_cluster[[19]], list_UMAPs_by_cluster[[20]], list_UMAPs_by_cluster[[21]], list_UMAPs_by_cluster[[22]], list_UMAPs_by_cluster[[23]], ncol = 8)

composite_plot

save

ggsave("../images_to_export/clusters_composite_plot.png", plot = composite_plot, device = "png", path = NULL, scale = 1, width = 21, height = 10, units = "cm", dpi = 300, limitsize = TRUE)

9. Subset sexual cells

Make a subsetted Seurat object of sexual cells.

Include the pre-branch too as well as any weird clusters that may have clustered out.

it’s been a while since we looked at the clusters so let’s check them out again:

## Plot
DimPlot(tenx.justwt.integrated, label = TRUE, repel = FALSE, pt.size = 0.05, group.by = "seurat_clusters", dims = c(1,2), reduction = "umap") + coord_fixed()

## plot
list_UMAPs_by_cluster[[1]] + list_UMAPs_by_cluster[[2]] + list_UMAPs_by_cluster[[3]] + list_UMAPs_by_cluster[[4]] + list_UMAPs_by_cluster[[5]] + list_UMAPs_by_cluster[[6]] + list_UMAPs_by_cluster[[7]] + list_UMAPs_by_cluster[[8]] + list_UMAPs_by_cluster[[9]] + list_UMAPs_by_cluster[[10]] + list_UMAPs_by_cluster[[11]] + list_UMAPs_by_cluster[[12]] + list_UMAPs_by_cluster[[13]] + list_UMAPs_by_cluster[[14]] + list_UMAPs_by_cluster[[15]] + list_UMAPs_by_cluster[[16]] + list_UMAPs_by_cluster[[17]] + list_UMAPs_by_cluster[[18]] + list_UMAPs_by_cluster[[19]] + list_UMAPs_by_cluster[[20]] + list_UMAPs_by_cluster[[21]] + list_UMAPs_by_cluster[[22]] + list_UMAPs_by_cluster[[23]] + list_UMAPs_by_cluster[[24]]

Define cells and subset

asexual_early_clusters <- c(9, 4, 15, 8, 1, 14, 2, 10, 3, 0, 6, 5)
asexual_late_clusters <- c(7, 12, 18, 20, 23)
bipotentional_early_clusters <- # 0?
bipotential_clusters <- c(11) 
male_clusters <- c(16, 13)
female_clusters <- c(21, 22, 17, 19)

## define cells
cell_names_subset_monocle_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$monocle_sex %in% c("Asexual_Early", "Bipotential", "Male", "Female"), ])

## 3, 0, 6, 5 are early clusters of asexuals before the branch
cell_names_subset_cluster_ids <- rownames(tenx.justwt.integrated@meta.data[tenx.justwt.integrated@meta.data$seurat_clusters %in% c(male_clusters, female_clusters, bipotential_clusters, 3, 0, 6, 5), ])

cell_names_subset_intersect <- intersect(cell_names_subset_monocle_ids, cell_names_subset_cluster_ids)

## subset cells into new object
tenx.justwt.integrated.sex <- subset(tenx.justwt.integrated, cells = cell_names_subset_intersect)

inspect/check

## inspect object
tenx.justwt.integrated.sex

## look at original UMAP
DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, split.by = "experiment", dims = c(1,2), reduction = "umap") + coord_fixed()

Remove contaminant asexual cells

we want to remove:

## look at original UMAP
plot_sexual_subsetting <- DimPlot(tenx.justwt.integrated.sex, label = TRUE, repel = TRUE, pt.size = 0.1, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  geom_vline(aes(xintercept = -1, alpha = 5))

plot_sexual_subsetting
## extract cell embeddings
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated.sex@reductions[["umap"]]@cell.embeddings)

## subset anything lower than -0.8 in UMAP 2 and -0.1 in UMAP 1
remove_cells <- row.names(df_sex_cell_embeddings[which(df_sex_cell_embeddings$UMAP_1 < -1), ])

## plot these cells
DimPlot(tenx.justwt.integrated.sex, label = FALSE, repel = TRUE, pt.size = 0.1, cells.highlight = remove_cells, dims = c(1,2), reduction = "umap") + 
  coord_fixed() + 
  scale_color_manual(values=c("#000000", "#f54e1e")) + 
  theme_void() + 
  labs(title = paste("cells highlighted will be removed")) + 
  theme(plot.title = element_text(hjust = 0.5), legend.position = "none")

Final Subset

## make keep cells from the remove_cells
## make the not in function
'%ni%' <- Negate('%in%')
keep_cells <- colnames(tenx.justwt.integrated.sex)[which(colnames(tenx.justwt.integrated.sex) %ni% remove_cells)]

## subset
tenx.justwt.integrated.sex <- subset(tenx.justwt.integrated.sex, cells = keep_cells)

## inspect
tenx.justwt.integrated.sex

copy old clusters over

## copy old clusters
tenx.justwt.integrated.sex <- AddMetaData(tenx.justwt.integrated.sex, tenx.justwt.integrated.sex@meta.data$seurat_clusters, col.name = "post_integration_clusters")

10. Sex assignment of mutants

A. Seurat Method

## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- df[df$genetic_background =="PBANKA_820", ]
table(df_820$predicted.id, df_820$fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      69       1
  Asexual_Late   33     459      16
  Female          2     342     240
  Male          182      49       0
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- df[df$genetic_background =="PBANKA_820", ]
table(df_820$predicted.id, df_820$fluoresence_sorted_on)

inspect gd1

df[which(df$predicted.id == "Female_1" & df$identity_name_updated == "gd1"), ][, 118:146]

Calculate sex ratios

## use designations above for sexes
male_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Male", ])
female_cells <- rownames(mutant_seurat@meta.data[mutant_seurat@meta.data$predicted.id == "Female", ])
ss2_mutants_final_male <- subset(mutant_seurat, cells = male_cells)
ss2_mutants_final_female <- subset(mutant_seurat, cells = female_cells)

## inspect
ss2_mutants_final_male
ss2_mutants_final_female
## calculate sex ratios
##subset out H, sorted cells:
df_male <- ss2_mutants_final_male@meta.data[ss2_mutants_final_male@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_male)

df_female <- ss2_mutants_final_female@meta.data[ss2_mutants_final_female@meta.data$exclude_for_sex_ratio == FALSE,]

dim(df_female)

## make dataframe
df_sex_ratio <- merge(
  as.data.frame(table(df_male$sub_name_updated)), 
  as.data.frame(table(df_female$sub_name_updated)), 
  by = "Var1", all=TRUE)

# or use identity_updated

## add names
names(df_sex_ratio) <- c("genotype", "male", "female")

## change the NAs to 0
df_sex_ratio[is.na(df_sex_ratio)] <- 0

## collapse 820 wild-types together
combined_m <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$male + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$male
combined_f <- df_sex_ratio[df_sex_ratio$genotype == "WT-820_3_5", ]$female + df_sex_ratio[df_sex_ratio$genotype == "WT-820", ]$female
df_sex_ratio <- rbind(df_sex_ratio, c("WT-820-combined", combined_m, combined_f))
# remove old rows
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-820_3_5" | df_sex_ratio$genotype == "WT-820"), ]
# need to make numeric again
df_sex_ratio$male <- as.numeric(df_sex_ratio$male)
df_sex_ratio$female <- as.numeric(df_sex_ratio$female)
df_sex_ratio$genotype <- as.character(df_sex_ratio$genotype)
# add name for WT combined
df_sex_ratio$genotype[17] <- "WT-820-combined"

## calculate sex ratio
df_sex_ratio$sex_ratio <- (df_sex_ratio$male + 0.1)/(df_sex_ratio$female + 0.1)

## log sex ratio
df_sex_ratio$sex_ratio_log <- log10(df_sex_ratio$sex_ratio)

##view
df_sex_ratio
## remove WT-2 because it is really inappropriate to have a sex ratio for this:
df_sex_ratio <- df_sex_ratio[-which(df_sex_ratio$genotype == "WT-md5"),]

plot

library(latex2exp) # so you can plot the fraction, it's on CRAN `install.packages("latex2exp")`

## make extra column for plotting aesthetics:
df_sex_ratio$above <- df_sex_ratio$sex_ratio_log > 0

## make extra column with ratio in it:
df_sex_ratio$genotype_with_n <- paste0(df_sex_ratio$genotype, " (", df_sex_ratio$male, "/", df_sex_ratio$female, ")")

## reorder genotype so it is in the correct order for plotting
df_sex_ratio$genotype_with_n <- factor(df_sex_ratio$genotype_with_n, levels = df_sex_ratio$genotype_with_n[order(df_sex_ratio$sex_ratio_log)])

## plot
sex_ratio_plot <- ggplot(df_sex_ratio, aes(sex_ratio_log, genotype_with_n, color = above)) +
      ## add the lines for the lollipop plot
      geom_segment(aes(x = 0, y = genotype_with_n, xend = sex_ratio_log, yend = genotype_with_n), color = "grey50") +
      ## add the points for the lollipop plot
      geom_point(aes(size = 4)) +
      ## add the wild-type rectangle
      annotate("rect", xmin= -0.23182478, xmax = 1.00105797, ymin=-Inf , ymax=Inf, alpha=0.4, color=NA,linetype = 2, fill="#999999") +
      ## make prettier
      theme_classic() +
      theme(legend.position = "none", text=element_text(size=16, family="Arial")) + 
      ## change axis labels
      labs(y = TeX("$Genotype\ \\left(\\frac{n_{male}}{n_{female}}\\right)$")) +
      #labs(y = expression(paste("Genotype", group("(", frac(paste("n male"), "n female"), ")")))) +
      xlab(expression(paste("Sex Ratio (", log[10], 
                               group("(",
                                      frac(paste("n male + 0.1"), 
                                           paste("n female + 0.1")),
                                   ")"), ")" ))) +
      ## change colours of lollipops
      scale_colour_manual(values = c("#a52b1e", "#016c00")) +
      ## annotate phenotypes
      geom_hline(aes(yintercept = 5.5)) #+
      #geom_hline(aes(yintercept = 14.5))

print(sex_ratio_plot)

### CHANGE TO BIG BRACKET HERE: https://www.overleaf.com/learn/latex/Brackets_and_Parentheses 

#paste("Sex Ratio", "\n", "log10((n male + 0.1)/(n female + 0.1))")
#theme(legend.position = "none", text=element_text(size=16, family="Arial"))

## fraction titles: https://groups.google.com/forum/#!topic/ggplot2/bgNRnZ82hJY 
## https://uc-r.github.io/lollipop

#ggsave(filename = "../images_to_export/sex_ratio_plot.png", device = "png", width = 7, height = 7, units = "in")

B. SCMAP Method

Build the index

### Making an ortholog reference index

## load in mca data
#counts <- read.csv("../scmap/allpb10x_counts.csv", row.names = 1)
#pheno <- read.csv("../scmap/allpb10x_pheno.csv")
#ggplot(pheno, aes(x=PC2_3d, y = PC3_3d,colour=absclust3)) + geom_point()

## load required libraries
library(scmap) #https://bioconductor.org/packages/release/bioc/html/scmap.html 
library(SingleCellExperiment) #

#prep the SCE, if was originally a Suerat object need the dfs to be regular matrices
#pb_filtered_sce_orth <- pb_filtered_sce_orth[, colData(pb_filtered_sce_orth)$absclust3 != "8"]
#sce <- pb_filtered_sce_orth
#pca <- plotPCA(sce)
#pcs <- pca$data
#table(rownames(pcs)==colnames(sce))
#colData(sce) <- cbind(colData(sce), pcs)
#rowData(sce)$feature_symbol <- rowData(sce)$gene

## extract data from Seurat
#cells_tenx <- rownames(tenx.justwt.integrated@meta.data[which(tenx.justwt.integrated@meta.data$experiment == "tenx_5k"), ])
#tenx.justwt.integrated.10k <- subset(tenx.justwt.integrated, cells = cells_tenx)
counts = as.matrix(GetAssayData(tenx.justwt.integrated, slot = "counts", assay = "RNA"))
pheno = as.data.frame(tenx.justwt.integrated@meta.data)

## add UMAP coordinates
df_sex_cell_embeddings <- as.data.frame(tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings)
pheno <- cbind(pheno, df_sex_cell_embeddings)

## Set up object
sce <- SingleCellExperiment(list(counts=counts),
    colData=DataFrame(label=pheno),
    rowData=DataFrame(feature_symbol=rownames(counts)))
sce

## manual logging
#counts_1 <- assay(sce, "counts")
#libsizes <- colSums(counts_1)
#size.factors <- libsizes/mean(libsizes)
#logcounts(sce) <- log2(t(t(counts_1)/size.factors) + 1)
#counts(sce) <- as.matrix(counts(sce))
#logcounts(sce) <- as.matrix(logcounts(sce))
logcounts(sce) <- as.matrix(GetAssayData(tenx.justwt.integrated, slot = "data", assay = "RNA"))

## remove features with duplicated names
sce <- sce[!duplicated(rownames(sce)), ]

## build scmap-cell reference index, save this rds
sce <- selectFeatures(sce, suppress_plot = FALSE, n_features = 2000)
table(rowData(sce)$scmap_features)
set.seed(1)
sce <- indexCell(sce, M = 50, k = 80)
names(metadata(sce)$scmap_cell_index)
#length(metadata(sce)$scmap_cell_index$subcentroids)
#dim(metadata(sce)$scmap_cell_index$subcentroids[[1]])
#metadata(sce)$scmap_cell_index$subcentroids[[1]][,1:5]
#dim(metadata(sce)$scmap_cell_index$subclusters)

#saveRDS(pb_filtered_sce_orth, file="pb_filtered_sce_orthindex_20181109.rds")

Map to the index

## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$topcell_sp, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   0      89       2
  Asexual_Late    5     150       3
  Female          2      84      54
  Male          158      47       0
  unassigned     52     549     198
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$topcell_sp, df_820$label.fluoresence_sorted_on)
table(colData(mutants.sce)$topcell_sp, colData(mutants.sce)$label.identity_name_updated)
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$stage_pred, df_820$label.fluoresence_sorted_on)
               
                GFP Hoechst mCherry
  Asexual_Early   1      81       2
  Asexual_Late    3     153       3
  Bipotential     0       1       0
  Female          2      83      52
  Male          156      47       0
  unassigned     55     554     200
## see how this overlaps with fluorescence sorted on for 820 to confirm accuracy
df_820 <- colData(mutants.sce)[colData(mutants.sce)$label.genetic_background =="PBANKA_820", ]
table(df_820$stage_pred, df_820$label.fluoresence_sorted_on)
table(colData(mutants.sce)$stage_pred, colData(mutants.sce)$label.identity_name_updated)

make final plot with MCA data below

## Read in MCA data
pheno <- read.csv("../scmap/allpb10x_pheno.csv")
## extract rows needed for plotting
df_plot <- pheno[,c("PC2_3d", "PC3_3d", "absclust3")]
df_plot$experiment <- df_plot$absclust3

## extract rows needed for plotting from mapped object
df_plot_pm <- as.data.frame(colData(pm_ss2_field.sce.orth))
df_plot_pm <- df_plot_pm[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pm$experiment <- "pm"
colnames(df_plot_pm) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## extract rows needed for plotting from mapped object
df_plot_pf <- as.data.frame(colData(pf_ss2_field.sce.orth))
df_plot_pf <- df_plot_pf[ ,c("X_snap", "Y_snap", "label.absclust3")]
df_plot_pf$experiment <- "pf"
colnames(df_plot_pf) <- c("PC2_3d", "PC3_3d", "absclust3", "experiment")

## bind together
df_plot <- rbind(df_plot, df_plot_pf, df_plot_pm)

colors <- c("6"="#78C679",
            "2"="#D1EC9F",
            "0"="#FEB24C",
            "1"="#F4CF63",
            "3"="#FEEEAA",
            "4"="#85B1D3",
            "7"="#9ecae1",
            "5"="#C9E8F1",
            "M"= "#B7B7D8",
            "F"="#9C96C6",
            "unassigned"="black",
            "pm" = "#dc65a4",
            "pf" = "#24245f")

## add alpha for plotting
df_plot$alpha[!df_plot$experiment == "pm"] <- 0.5
df_plot$alpha[df_plot$experiment == "pm"] <- 1
df_plot$alpha[df_plot$experiment == "pf"] <- 1

##plot
scmap_pca <- ggplot(df_plot, aes(x=PC2_3d, y = PC3_3d,colour=experiment, alpha = alpha)) + 
  geom_point() +
  theme_void() +
  scale_color_manual(values = colors) +
  ## remove alpha scale
  scale_alpha_continuous(guide=FALSE)
  ## draw ring around field samples
  #geom_point(data=df_plot[df_plot$experiment == "pm", ], pch=21, fill=NA, size=2, colour="black", stroke=1) +
  ## make non-field samples more opaque
  #geom_point(data=df_plot[-df_plot$experiment == "pm", ], alpha = 0.2)

## view
scmap_pca_2 <- scmap_pca + 
  guides(colour=guide_legend(override.aes = list(size=4)))

scmap_pca_2

save

#ggsave("../images_to_export/field_samples_scmap.png", plot = scmap_pca_2, device = "png", path = NULL, scale = 1, width = 15, height = 10, units = "cm", dpi = 300, limitsize = TRUE)

Overlap and validation

11. Save and Export

save

Save environment

## This saves everything in the global environment for easy recall later
#save.image(file = "GCSKO_merge.RData")
#load(file = "GCSKO_merge.RData")

Save object(s)

## Save an object to a file
saveRDS(tenx.justwt.integrated.sex, file = "../data_to_export/tenx.justwt.integrated.sex.RDS")
## Restore the object
#readRDS(file = "../data_to_export/tenx.mutant.integrated.sex.RDS")

## save integrated object to file
saveRDS(tenx.justwt.integrated, file = "../data_to_export/tenx.justwt.integrated.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

## save monocle object
saveRDS(monocle.object.all, file = "../data_to_export/monocle.object.all.RDS") 
## restore the object
#monocle.object.all <- readRDS("../data_to_export/monocle.object.all.RDS")

## save integrated object to file
#saveRDS(GCSKO_mutants, file = "../data_to_export/GCSKO_mutants.RDS") 
## restore the object
#tenx.justwt.integrated <- readRDS("../data_to_export/tenx.justwt.integrated.RDS")

## extract UMAP coordinates and metadata
## extract metadata
mca_website_df <- tenx.justwt.integrated@meta.data

## add umap - merge on row names and then make sure row names are not dropped or added
mca_website_df <- transform(merge(mca_website_df, tenx.justwt.integrated@reductions[["umap"]]@cell.embeddings, by=0, all=TRUE), row.names=Row.names, Row.names=NULL)

## send this to sunil:
# ggplot(mca_website_df, aes(x = UMAP_1, y = UMAP_2)) +
# geom_point(col = mca_website_df$pt_id_cols) +
# theme_void() +
# coord_fixed()

## export
write.csv(mca_website_df, file = "../data_to_export/mca_website_df.csv")

Clean up

#rm(ss2_wt_cells)
#rm(tenx.justwt.integrated)
#rm(tenx.justwt.list)

final figure construction

Cowplot(plot_grid), patchwork(wrap_plots), and ggpubr can all allow multiple plots to be plotted together.

## A
# umap_id_pt
## B
# marker gene expression
## C
# Mutant gene expression
## D
# Modules

#Figure_A <- grid.arrange(arrangeGrob(QC_composite_plot, QC_mito_violin, QC_mito_graph, QC_by_genotype, mapping_rate_plot), nrow=3), nrow=2, heights=c(10,2))

## cowplot method
## can use this for labels: toupper(letters)[1:10]

## C. Mutant genes
mutant_genes_figure <- plot_grid(
                                 ## marker genes starts
                                 marker_gene_plot_FAMB,
                                 marker_gene_plot_MSP8,
                                 marker_gene_plot_MSP1,
                                 marker_gene_plot_AP2G,
                                 marker_gene_plot_CCP2,
                                 marker_gene_plot_MG1,
                                 ## mutant genes starts  
                                 marker_gene_plot_gd1,
                                 marker_gene_plot_md1,
                                 marker_gene_plot_md2,
                                 marker_gene_plot_md3,
                                 marker_gene_plot_md4, 
                                 marker_gene_plot_md5,
                                 marker_gene_plot_fd1,
                                 marker_gene_plot_fd2,
                                 marker_gene_plot_fd3,
                                 marker_gene_plot_fd4, 
  label_size = 1, 
  nrow = 4)

## labels as uppercase letters:
#c(toupper(letters)[2:17])
# labels as roman numerals:
# c(tolower(as.roman(c(2:17))

Figure_publication <- plot_grid(umap_id_pt + theme(plot.margin = unit(c(0, 0, 0, 0), "cm")), 
                                mutant_genes_figure,
                                ## add empty plot to give spacing
                                ggplot() + theme_void(),
                                labels = c('A', 'B'), 
                                label_size = 12, 
                                ncol = 2, 
                                nrow=2, 
                                rel_heights = c(1, 1, 4), 
                                rel_widths = c(1, 2, 3))

Figure_publication

save

ggsave("../images_to_export/Figure_C.png", plot = Figure_publication, device = "png", path = NULL, scale = 1, width = 21, height = 29.7, units = "cm", dpi = 300, limitsize = TRUE)
layout <- "
AAABBB
CCDDEE
FFGGHH
IIJJKK
"

Figure_publication_A <- (composition_umap_10x + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) +
(composition_umap_ss2 + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10))) + 
plot_layout(ncol = 2)

Figure_publication <- Figure_publication_A +
#(UMAP_hoo + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Asexual Cycle Real Timepoint")) +
#(UMAP_kasia + theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 10)) + labs(title="Predicted Gametocytogenesis Real Timepoint")) +
  ## marker genes
marker_gene_plot_FAMB +
marker_gene_plot_MSP8 +
marker_gene_plot_MSP1 +
marker_gene_plot_CDPK5 +
marker_gene_plot_AP2G +
marker_gene_plot_CCP2 +
marker_gene_plot_MG1 +
marker_gene_plot_ORC1 +
marker_gene_plot_MCM4 +
  ## mutant genes starts  
#marker_gene_plot_gd1 +
#marker_gene_plot_md1 +
#marker_gene_plot_md2 +
#marker_gene_plot_md3 +
#marker_gene_plot_md4 + 
#marker_gene_plot_md5 +
#marker_gene_plot_fd1 +
#marker_gene_plot_fd2 +
#marker_gene_plot_fd3 +
#marker_gene_plot_fd4 + 
plot_layout(ncol = 6, 
            widths = c(1, 1, 1, 1, 1 ,1),
            heights = c(2, 1, 1, 1),
            design = layout
            )

Figure_publication

save

sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
 [1] stats4    parallel  grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] colourvalues_0.3.7          readxl_1.3.1                destiny_3.2.0               circlize_0.4.12            
 [5] gganimate_1.0.7             shiny_1.5.0                 monocle3_0.2.3.0            SingleCellExperiment_1.10.1
 [9] SummarizedExperiment_1.18.2 DelayedArray_0.14.1         matrixStats_0.57.0          GenomicRanges_1.40.0       
[13] GenomeInfoDb_1.24.2         IRanges_2.22.2              S4Vectors_0.26.1            Biobase_2.48.0             
[17] BiocGenerics_0.34.0         Nebulosa_1.2.0              reshape2_1.4.4              Hmisc_4.4-1                
[21] Formula_1.2-4               survival_3.2-7              lattice_0.20-41             gridExtra_2.3              
[25] dplyr_1.0.2                 patchwork_1.0.1             ggplot2bdc_0.3.2            cowplot_1.1.0              
[29] ggpubr_0.4.0                ggplot2_3.3.2               viridis_0.5.1               viridisLite_0.3.0          
[33] Seurat_3.2.2                colorspace_1.4-1           

loaded via a namespace (and not attached):
  [1] ggthemes_4.2.4            coda_0.19-4               tidyr_1.1.2               knitr_1.30               
  [5] irlba_2.3.3               data.table_1.13.2         rpart_4.1-15              RCurl_1.98-1.2           
  [9] generics_0.0.2            callr_3.5.1               leidenbase_0.1.2          usethis_1.6.3            
 [13] RANN_2.6.1                proxy_0.4-24              future_1.19.1             spatstat.data_1.4-3      
 [17] httpuv_1.5.4              assertthat_0.2.1          gifski_0.8.6              xfun_0.18                
 [21] hms_0.5.3                 evaluate_0.14             promises_1.1.1            DEoptimR_1.0-8           
 [25] fansi_0.4.1               progress_1.2.2            DBI_1.1.0                 igraph_1.2.6             
 [29] htmlwidgets_1.5.2         spdep_1.1-5               purrr_0.3.4               ellipsis_0.3.1           
 [33] RSpectra_0.16-0           crosstalk_1.1.0.1         ks_1.12.0                 backports_1.1.10         
 [37] deldir_0.1-29             vctrs_0.3.4               TTR_0.24.2                remotes_2.2.0            
 [41] ROCR_1.0-11               abind_1.4-5               RcppEigen_0.3.3.7.0       withr_2.3.0              
 [45] grr_0.9.5                 robustbase_0.93-7         checkmate_2.0.0           vcd_1.4-8                
 [49] sctransform_0.3.1         xts_0.12.1                prettyunits_1.1.1         mclust_5.4.7             
 [53] goftest_1.2-2             cluster_2.1.0             lazyeval_0.2.2            laeken_0.5.1             
 [57] crayon_1.3.4              units_0.6-7               slam_0.1-47               pkgconfig_2.0.3          
 [61] labeling_0.4.2            tweenr_1.0.1              nlme_3.1-149              pkgload_1.1.0            
 [65] nnet_7.3-14               devtools_2.3.2            rlang_0.4.8               globals_0.13.1           
 [69] lifecycle_0.2.0           miniUI_0.1.1.1            rsvd_1.0.3                cellranger_1.1.0         
 [73] rprojroot_1.3-2           polyclip_1.10-0           RcppHNSW_0.3.0            lmtest_0.9-38            
 [77] Matrix_1.2-18             raster_3.3-13             carData_3.0-4             Matrix.utils_0.9.8       
 [81] boot_1.3-25               zoo_1.8-8                 base64enc_0.1-3           ggridges_0.5.2           
 [85] GlobalOptions_0.1.2       processx_3.4.4            pheatmap_1.0.12           png_0.1-7                
 [89] bitops_1.0-6              KernSmooth_2.23-17        DelayedMatrixStats_1.10.1 classInt_0.4-3           
 [93] shape_1.4.5               stringr_1.4.0             jpeg_0.1-8.1              rstatix_0.6.0            
 [97] ggsignif_0.6.0            scales_1.1.1              memoise_1.1.0             magrittr_2.0.1           
[101] plyr_1.8.6                hexbin_1.28.1             ica_1.0-2                 gdata_2.18.0             
[105] zlibbioc_1.34.0           compiler_4.0.3            RColorBrewer_1.1-2        pcaMethods_1.80.0        
[109] fitdistrplus_1.1-1        cli_2.1.0                 LearnBayes_2.15.1         XVector_0.28.0           
[113] listenv_0.8.0             pbapply_1.4-3             ps_1.4.0                  htmlTable_2.1.0          
[117] ggplot.multistats_1.0.0   MASS_7.3-53               mgcv_1.8-33               tidyselect_1.1.0         
[121] stringi_1.5.3             forcats_0.5.0             yaml_2.2.1                latticeExtra_0.6-29      
[125] ggrepel_0.8.2             pbmcapply_1.5.0           tools_4.0.3               future.apply_1.6.0       
[129] rio_0.5.16                rstudioapi_0.11           foreign_0.8-80            smoother_1.1             
[133] scatterplot3d_0.3-41      farver_2.0.3              Rtsne_0.15                digest_0.6.27            
[137] BiocManager_1.30.10       Rcpp_1.0.6                car_3.0-10                broom_0.7.2              
[141] later_1.1.0.1             RcppAnnoy_0.0.16          httr_1.4.2                sf_0.9-6                 
[145] fs_1.5.0                  tensor_1.5                ranger_0.12.1             reticulate_1.18          
[149] splines_4.0.3             uwot_0.1.8                expm_0.999-5              spatstat.utils_1.17-0    
[153] sp_1.4-4                  spData_0.3.8              plotly_4.9.2.1            sessioninfo_1.1.1        
[157] xtable_1.8-4              jsonlite_1.7.1            spatstat_1.64-1           testthat_2.3.2           
[161] R6_2.5.0                  gmodels_2.18.1            pillar_1.4.6              htmltools_0.5.1.1        
[165] mime_0.9                  glue_1.4.2                fastmap_1.0.1             VIM_6.1.0                
[169] class_7.3-17              codetools_0.2-16          utf8_1.1.4                pkgbuild_1.1.0           
[173] mvtnorm_1.1-1             tibble_3.0.4              curl_4.3                  leiden_0.3.3             
[177] gtools_3.8.2              zip_2.1.1                 openxlsx_4.2.2            limma_3.44.3             
[181] rmarkdown_2.5             desc_1.2.0                munsell_0.5.0             e1071_1.7-4              
[185] GenomeInfoDbData_1.2.3    haven_2.3.1               gtable_0.3.0             

Appendix

Session Info

Expression plots

Expression - raw - Viridis

## find a good ring marker, to see if there is a better one than the ones reported
#markers_ring <- FindMarkers(tenx.justwt.integrated, ident.1 = c("4", "5", "16", "11", "7", "3", "9", "0", "22"))
#head(markers_ring)

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 


marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(ccp2), "(Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0416100", coord.fixed = TRUE, 
                                    #min.cutoff = "q1", 
                                    dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(mg1), "(Male)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1437500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(ap2g), "(Commitment)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0831000", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(msp1), "(Schizont)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1102200", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(msp8), "(Asexual)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1101300", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(sbp1), "(Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0722600", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(fam-b2),  "(Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

marker_gene_plot_HSP70 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0711900", coord.fixed = TRUE, 
                                      #min.cutoff = "q1", 
                                      dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste(italic(HSP70),  "(Reporter)","\n", "PBANKA_0711900")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)))

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)

marker_gene_plot_all

## patchwork method
#marker_gene_plot_FAMB + marker_gene_plot_MSP8 + marker_gene_plot_MSP1 + marker_gene_plot_AP2G + marker_gene_plot_CCP2 + marker_gene_plot_MG1 + marker_gene_plot_HSP70

Expression - raw - purple


marker_gene_ramp <- colorRampPalette(c("#D3D3D3", "#1D1564"))(50)

marker_gene_plot_CCP2 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1319500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("CCP2 (Female)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

marker_gene_plot_MG1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0416100", coord.fixed = TRUE, 
                                    #min.cutoff = "q1", 
                                    dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MG1 (Male)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

marker_gene_plot_AP2G <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1437500", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("AP2G (Commitment)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

marker_gene_plot_MSP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0831000", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP1 (Schizont)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

marker_gene_plot_MSP8 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1102200", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("MSP8 (Asexual)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

marker_gene_plot_SBP1 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-1101300", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("SBP1 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

marker_gene_plot_FAMB <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0722600", coord.fixed = TRUE, 
                                     #min.cutoff = "q1", 
                                     dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("Fam-b2 (Ring)")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

marker_gene_plot_HSP70 <- FeaturePlot(tenx.justwt.integrated, features = "PBANKA-0711900", coord.fixed = TRUE, 
                                      #min.cutoff = "q1", 
                                      dims = c(1,2), reduction = "umap", pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("(HSP70; Reporter)","\n", "PBANKA_0711900")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_colour_gradientn(colours=marker_gene_ramp)

## plot
## cowplot method
marker_gene_plot_all <- plot_grid(marker_gene_plot_FAMB, marker_gene_plot_MSP8, marker_gene_plot_MSP1, marker_gene_plot_AP2G, marker_gene_plot_CCP2, marker_gene_plot_MG1, marker_gene_plot_HSP70, nrow=3)

marker_gene_plot_all

Expression - data - purple

# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-1435200        GCSKO-20  FD4 
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-0413400    GCSKO-10_820  MD5
# PBANKA-0828000         GCSKO-3  GD1
# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-1144800        GCSKO-28  FD5


marker_gene_plot_17 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1418100", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_2 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0102400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md3")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_19 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0716500", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_20 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1435200", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd4")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_13 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0902300", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_10 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0413400", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md5")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_3 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-0828000", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("gd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_oom <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1302700", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_29 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1447900", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("md2")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

marker_gene_plot_21 <- FeaturePlot(tenx.justwt.integrated, dims = c(1,2), reduction = "umap", features = "PBANKA-1454800", coord.fixed = TRUE,  pt.size = 1, order = TRUE) + 
  theme_void() + 
  labs(title = paste("fd1")) + 
  theme(plot.title = element_text(hjust = 0.5, family="Arial", size = 20, face = "bold")) + 
  scale_color_continuous_sequential(palette = "Purples 2") +
  ## add sex symbols
  annotate("text", x = 3.8, y = 1.5, label = male_symbol, size=7, color="gray") + 
  annotate("text", x = 2, y = 2.8, label = female_symbol, size=7, color="gray")

##original label:
# labs(title = paste("(CCP2; Female)","\n", "PBANKA_1319500"))

## make composite plot
mutant_expression_composite <- wrap_plots(marker_gene_plot_17 , marker_gene_plot_2 , marker_gene_plot_19 , marker_gene_plot_20 , marker_gene_plot_13 , marker_gene_plot_10 , marker_gene_plot_3 , marker_gene_plot_oom , marker_gene_plot_29 , marker_gene_plot_21 , ncol = 4)
           
## print
mutant_expression_composite

Density Plots

Density - purple

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=marker_gene_ramp) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=marker_gene_ramp) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=marker_gene_ramp) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)

UMAP_composite_mutant_genes

Density -viridis

# PBANKA-1319500 - CCP2 - female - used in 820 line
# PBANKA-0416100 - MG1 - dynenin heavy chain - male - used in 820 line
# PBANKA-1437500 - AP2G - commitment
# PBANKA-0831000 - MSP1 - late asexual
# PBANKA-1102200 - MSP8 - early asexual (from Bozdech paper)
# PBANKA-0711900 - HSP70 - promoter used for GFP and RFP expression in the mutants
# PBANKA-1400400 - FAMB - ring marker - discovered by looking for marker genes in data
# PBANKA-0722600 - Fam-b2 - ring marker - https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5113031/ 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)

UMAP_composite_mutant_genes

Density - viridis

# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "ks")

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + coord_fixed() + theme_void() + labs(title = paste("md2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30)) )+ guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)

UMAP_composite_mutant_genes

## IF putting in MAIN - list_of_density_plots_mutant_genes[[2]] + coord_fixed() + theme_void() + theme(plot.title = element_text(hjust = 0.5), legend.text = element_text(size = 8), text=element_text(size=9)) + labs(title = paste("md1")) + scale_colour_gradientn(colours=c("#DCDCDC", plasma(30))) + guides(colour = guide_colourbar(barwidth = 0.3, barheight = 4.0, title = ""))
# PBANKA-0828000         GCSKO-3  GD1

# PBANKA-1302700       GCSKO-oom  MD1 
# PBANKA-1447900        GCSKO-29  MD2
# PBANKA-0102400         GCSKO-2  MD3 
# PBANKA-0716500        GCSKO-19  MD4 
# PBANKA-0413400    GCSKO-10_820  MD5

# PBANKA-1454800        GCSKO-21  FD1
# PBANKA-0902300        GCSKO-13  FD2
# PBANKA-1418100        GCSKO-17  FD3   
# PBANKA-1435200        GCSKO-20  FD4 

markers_list <- c("PBANKA-0828000", "PBANKA-1302700", "PBANKA-1447900", "PBANKA-0102400", "PBANKA-0716500", "PBANKA-0413400", "PBANKA-1454800", "PBANKA-0902300", "PBANKA-1418100", "PBANKA-1435200")

list_of_density_plots_mutant_genes <- plot_density(tenx.justwt.integrated, markers_list, joint = FALSE, combine = FALSE, dims = c(1,2), pal = "plasma", method = "wkde", slot = 'data')

## make composite plot
UMAP_composite_mutant_genes <- wrap_plots(list_of_density_plots_mutant_genes[[1]] + 
                                            coord_fixed() + 
                                            theme_void() + 
                                            labs(title = paste("gd1")) + 
                                            scale_color_continuous_sequential(palette = "Purples 2") + 
                                            guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[2]] + 
                               coord_fixed() + theme_void() + 
                               labs(title = paste("md1")) + 
                               scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[3]] + 
                               coord_fixed() + 
                               theme_void() + 
                               labs(title = paste("md2")) + scale_color_continuous_sequential(palette = "Purples 2") + 
                               guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[4]] + coord_fixed() + theme_void() + labs(title = paste("md3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[5]] + coord_fixed() + theme_void() + 
  labs(title = paste("md4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[6]] + coord_fixed() + theme_void() + labs(title = paste("md5")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[7]] + coord_fixed() + theme_void() + labs(title = paste("fd1")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[8]] + coord_fixed() + theme_void() + labs(title = paste("fd2")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[9]] + coord_fixed() + theme_void() + labs(title = paste("fd3")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             list_of_density_plots_mutant_genes[[10]] + coord_fixed() + theme_void() + labs(title = paste("fd4")) + scale_color_continuous_sequential(palette = "Purples 2") + guides(colour = guide_colourbar(barwidth = 0.5, title = "")),
                             ncol = 4)

## old colour scale: scale_colour_gradientn(colours=marker_gene_ramp )

UMAP_composite_mutant_genes
LS0tCnN1YnRpdGxlOiAnR2FtZXRvY3l0ZSBEZXZlbG9wbWVudCBpbiA8aT5QbGFzbW9kaXVtIGJlcmdoZWk8L2k+Jwp0aXRsZTogfAogICFbXSguLi9HQ1NLT19sb2dvLmpwZyl7d2lkdGg9MzAwcHh9ICAKICBNZXJnaW5nIFNtYXJ0LXNlcTIgYW5kIDEwWCBEYXRhc2V0cyAtIHdpbGQtdHlwZSBvbmx5CmF1dGhvcjogIltBbmRyZXcgUnVzc2VsbF0oaHR0cHM6Ly9hamNydXNzZWxsLndpeHNpdGUuY29tL215c2l0ZS9hYm91dCkiCmluc3RpdHV0ZTogV2VsbGNvbWUgU2FuZ2VyIEluc3RpdHV0ZQpkYXRlOiAnYHIgZm9ybWF0KFN5cy5EYXRlKCksICIlQiAlZCwgJVkiKWAnCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICAjdG9jX2Zsb2F0OiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KKioqCiMgMS4gSW50cm9kdWN0aW9uIGFuZCBBaW1zIHsudGFic2V0fQoKV2UgaGF2ZSBxdWFsaXR5LWNvbnRyb2xsZWQgdGhlIDEwWCBkYXRhIGFuZCB0aGUgU1MyIGRhdGEgYW5kIG5vdyBhcmUgbGVmdCB3aXRoIHRoZSBmb2xsb3dpbmcgb2JqZWN0czoKCjEwWCA1SyBkYXRhIC0gcGJfc2V4X2ZpbHRlcmVkCgoxMFggMzBLIGRhdGEgLSBwYl8zMGtfc2V4X2ZpbHRlcmVkIAoKU1MyIG11dGFudCBkYXRhIC0gc3MyX211dGFudHNfZmluYWwKCiMgMi4gUmVhZCBpbiB0aGUgZGF0YSAgey50YWJzZXR9CgojIyMgTG9hZC9JbnN0YWxsIHRoZSBSZXF1aXJlZCBQYWNrYWdlcwoKYGBge3IgbG9hZCBwYWNrYWdlcywgZWNobyA9IEZBTFNFfQojIyBDUkFOIHBhY2thZ2VzCgojIyBQYXRod29yayBpcyBuZWVkZWQgdG8gc3RpY2ggcGxvdHMgdG9nZXRoZXIgdXNpbmcgJysnCmlmKHJlcXVpcmUoInBhdGNod29yayIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgicGF0Y2h3b3JrIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIHBhdGNod29yayIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwYXRjaHdvcmsiKQogICAgaWYocmVxdWlyZShwYXRjaHdvcmspKXsKICAgICAgICBwcmludCgicGF0Y2h3b3JrIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgcGF0Y2h3b3JrIikKICAgIH0KfQoKIyMgdmlyaWRpcyBhbGxvd3MgZGlmZmVyZW50IGNvbG91cnMgdG8gYmUgYWRkZWQgdG8gcGxvdHMKaWYocmVxdWlyZSgidmlyaWRpcyIsIHF1aWV0bHkgPSBUUlVFKSl7CiAgICBwcmludCgidmlyaWRpcyBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCB2aXJpZGlzIikKICAgIGluc3RhbGwucGFja2FnZXMoInZpcmlkaXMiKQogICAgaWYocmVxdWlyZSh2aXJpZGlzKSl7CiAgICAgICAgcHJpbnQoInZpcmlkaXMgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCB2aXJpZGlzIikKICAgIH0KfQoKIyMgU2V1cmF0IGlzIG5lZWRlZCBmb3IgbW9zdCBvZiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJTZXVyYXQiLCBxdWlldGx5ID0gVFJVRSkpewogICAgcHJpbnQoIlNldXJhdCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBTZXVyYXQiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiU2V1cmF0IikKICAgIGlmKHJlcXVpcmUoU2V1cmF0KSl7CiAgICAgICAgcHJpbnQoIlNldXJhdCBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIFNldXJhdCIpCiAgICB9Cn0KCiMjIGNvd3Bsb3QgaXMgbmVlZGVkIGZvciBwbG90cyBpbiB0aGlzIHNjcmlwdAppZihyZXF1aXJlKCJjb3dwbG90IikpewogICAgcHJpbnQoImNvd3Bsb3QgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgY293cGxvdCIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjb3dwbG90IikKICAgIGlmKHJlcXVpcmUoY293cGxvdCkpewogICAgICAgIHByaW50KCJjb3dwbG90IGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgY293cGxvdCIpCiAgICB9Cn0KCiMjIGdyaWRFeHRyYSBpcyBuZWVkZWQgZm9yIGdyaWQgZ3JhcGhpY3MgdG8gcGxvdCBtdWx0aXBsZSBwbG90cyBpbiB0aGUgc2FtZSB2aWV3CmlmKHJlcXVpcmUoImdyaWRFeHRyYSIpKXsKICAgIHByaW50KCJncmlkRXh0cmEgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgZ3JpZEV4dHJhIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWRFeHRyYSIpCiAgICBpZihyZXF1aXJlKGdyaWRFeHRyYSkpewogICAgICAgIHByaW50KCJncmlkRXh0cmEgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkRXh0cmEiKQogICAgfQp9CgojIyBncmlkIGlzIG5lZWRlZCBmb3IgZ3JpZC5hcnJhbmdlIGZ1bmN0aW9uIHRvIGNoYW5nZSBzaXplIG9mIHRpdGxlCmlmKHJlcXVpcmUoImdyaWQiKSl7CiAgICBwcmludCgiZ3JpZCBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBncmlkIikKICAgIGluc3RhbGwucGFja2FnZXMoImdyaWQiKQogICAgaWYocmVxdWlyZShncmlkKSl7CiAgICAgICAgcHJpbnQoImdyaWQgaW5zdGFsbGVkIGFuZCBsb2FkZWQiKQogICAgfSBlbHNlIHsKICAgICAgICBzdG9wKCJjb3VsZCBub3QgaW5zdGFsbCBncmlkIikKICAgIH0KfQoKIyNmb3IgZG9pbmcgYnVsayBjb3JyZWxhdGlvbiBjYWxjdWxhdGlvbnMKaWYocmVxdWlyZSgiSG1pc2MiKSl7CiAgICBwcmludCgiSG1pc2MgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgSG1pc2MiKQogICAgaW5zdGFsbC5wYWNrYWdlcygiSG1pc2MiKQogICAgaWYocmVxdWlyZShIbWlzYykpewogICAgICAgIHByaW50KCJIbWlzYyBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIEhtaXNjIikKICAgIH0KfQoKIyMgcmVzaGFwZTIgdG8gbWVsdCBkYXRhZnJhbWVzIGZvciBwbG90dGluZzoKaWYocmVxdWlyZSgicmVzaGFwZTIiKSl7CiAgICBwcmludCgicmVzaGFwZTIgaXMgbG9hZGVkIGNvcnJlY3RseSIpCn0gZWxzZSB7CiAgICBwcmludCgidHJ5aW5nIHRvIGluc3RhbGwgcmVzaGFwZTIiKQogICAgaW5zdGFsbC5wYWNrYWdlcygicmVzaGFwZTIiKQogICAgaWYocmVxdWlyZShyZXNoYXBlMikpewogICAgICAgIHByaW50KCJyZXNoYXBlMiBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIHJlc2hhcGUyIikKICAgIH0KfQoKIyMgdG8gd29yayB3aXRoIGRhdGEgZnJhbWVzOgppZihyZXF1aXJlKCJkcGx5ciIpKXsKICAgIHByaW50KCJkcGx5ciBpcyBsb2FkZWQgY29ycmVjdGx5IikKfSBlbHNlIHsKICAgIHByaW50KCJ0cnlpbmcgdG8gaW5zdGFsbCBkcGx5ciIpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCiAgICBpZihyZXF1aXJlKGRwbHlyKSl7CiAgICAgICAgcHJpbnQoImRwbHlyIGluc3RhbGxlZCBhbmQgbG9hZGVkIikKICAgIH0gZWxzZSB7CiAgICAgICAgc3RvcCgiY291bGQgbm90IGluc3RhbGwgZHBseXIiKQogICAgfQp9CgojIyBub24tQ1JBTiBwYWNrYWdlcwoKIyMgdG8gbWFrZSBkZW5zaXR5IHBsb3RzIHNob3dpbmcgZ2VuZSBleHByZXNzaW9uCmlmKHJlcXVpcmUoIk5lYnVsb3NhIikpewogICAgcHJpbnQoIk5lYnVsb3NhIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoInRyeWluZyB0byBpbnN0YWxsIE5lYnVsb3NhIikKICAgIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigicG93ZWxsZ2Vub21pY3NsYWIvTmVidWxvc2EiKQogICAgaWYocmVxdWlyZShOZWJ1bG9zYSkpewogICAgICAgIHByaW50KCJOZWJ1bG9zYSBpbnN0YWxsZWQgYW5kIGxvYWRlZCIpCiAgICB9IGVsc2UgewogICAgICAgIHN0b3AoImNvdWxkIG5vdCBpbnN0YWxsIE5lYnVsb3NhIikKICAgIH0KfQoKIyMgbW9ub2NsZTMgdG8gY2FsY3VsYXRlIHBzZXVkb3RpbWU6CmlmKHJlcXVpcmUoIm1vbm9jbGUzIikpewogICAgcHJpbnQoIm1vbm9jbGUzIGlzIGxvYWRlZCBjb3JyZWN0bHkiKQp9IGVsc2UgewogICAgcHJpbnQoIlBsZWFzZSBpbnN0YWxsIG1vbm9jbGUzIChodHRwczovL2NvbGUtdHJhcG5lbGwtbGFiLmdpdGh1Yi5pby9tb25vY2xlMy9kb2NzL2luc3RhbGxhdGlvbi8pIikKfQoKIyMgc2V0IHRoZSBzZWVkIGZvciBib3RoIHRoZSBtaXh0dXJlIG1vZGVscyBhbmQgYWxzbyBmb3IgdGhlIHNhbXBsZSBmdW5jdGlvbiBsYXRlciBvbjoKc2V0LnNlZWQoLTkyNDk3KQpgYGAKCiMjIyBSZWFkIGluIHRoZSBEYXRhCgpzY3JlZW4gaGl0cwpgYGB7cn0KIyMgRURJVCAtIGNoYW5nZSB0aGlzIHRvIHRoZSBleGNlbCB0YWJsZSBvbmNlIHdlIGhhdmUgaXQgZmluYWxpemVkIGZvciB0aGUgc2NyZWVuCnNjcmVlbl9oaXRzIDwtIGMoIlBCQU5LQS0wNTE2MzAwIiwKIlBCQU5LQS0xMjE3NzAwIiwKIlBCQU5LQS0wNDA5MTAwIiwKIlBCQU5LQS0xMDM0MzAwIiwKIlBCQU5LQS0xNDM3NTAwIiwKIlBCQU5LQS0wODI3NTAwIiwKIlBCQU5LQS0wODI0MzAwIiwKIlBCQU5LQS0xNDI2OTAwIiwKIlBCQU5LQS0wMTA1MzAwIiwKIlBCQU5LQS0wOTIxMTAwIiwKIlBCQU5LQS0xMDAyNDAwIiwKIlBCQU5LQS0wODI5NDAwIiwKIlBCQU5LQS0xMzQ3MjAwIiwKIlBCQU5LQS0wODI4MDAwIiwKIlBCQU5LQS0wOTAyMzAwIiwKIlBCQU5LQS0xNDE4MTAwIiwKIlBCQU5LQS0xNDM1MjAwIiwKIlBCQU5LQS0xNDU0ODAwIiwKIlBCQU5LQS0wNzEyMzAwIiwKIlBCQU5LQS0wNDEwNTAwIiwKIlBCQU5LQS0xMTQ0ODAwIiwKIlBCQU5LQS0xMjMxNjAwIiwKIlBCQU5LQS0wNTAzMjAwIiwKIlBCQU5LQS0wMzA4OTAwIiwKIlBCQU5LQS0xMjE0NzAwIiwKIlBCQU5LQS0wNzA5OTAwIiwKIlBCQU5LQS0wMzExOTAwIiwKIlBCQU5LQS0wNzE2NTAwIiwKIlBCQU5LQS0xNDQ3OTAwIiwKIlBCQU5LQS0wMTAyMjAwIiwKIlBCQU5LQS0wNzEzNTAwIiwKIlBCQU5LQS0wMTAyNDAwIiwKIlBCQU5LQS0xMzAyNzAwIiwKIlBCQU5LQS0xMjM1OTAwIiwKIlBCQU5LQS0wNDAxMTAwIiwKIlBCQU5LQS0wNDEzNDAwIiwKIlBCQU5LQS0xMTI2OTAwIiwKIlBCQU5LQS0xNDI1OTAwIiwKIlBCQU5LQS0wNDE4MzAwIiwKIlBCQU5LQS0xNDY0NjAwIiwKIlBCQU5LQS0wODA2MDAwIikKYGBgCgpSZWFkIGluIGdlbmUgYW5ub3RhdGlvbnMKYGBge3J9CmdlbmVfYW5ub3RhdGlvbnMgPC0gcmVhZC50YWJsZSgiLi4vZGF0YS9SZWZlcmVuY2UvR2VuZXNCeVRheG9uX1N1bW1hcnkuY3N2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gVFJVRSkKZGltKGdlbmVfYW5ub3RhdGlvbnMpCgojIyBjb252ZXJ0IF8gdG8gLQpnZW5lX2Fubm90YXRpb25zJEdlbmUuSUQgPC0gZ3N1YigiXyIsICItIiwgZ2VuZV9hbm5vdGF0aW9ucyRHZW5lLklEKQpgYGAKCmxvYWQgaW4gZGF0YXNldHMKYGBge3J9CiMjIGxvYWQgdGhlIDEwWCBkYXRhc2V0CnBiX3NleF9maWx0ZXJlZCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC9wYl9zZXhfZmlsdGVyZWQuUkRTIikKIyMgbG9hZCB0aGUgU1MyIGRhdGFzZXQKc3MyX211dGFudHNfZmluYWwgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvc3MyX211dGFudHNfZmluYWwuUkRTIikKCiMjIGluc3BlY3QKcGFzdGUoIjEweCBkYXRhc2V0IikKcGJfc2V4X2ZpbHRlcmVkCnBhc3RlKCJTbWFydC1zZXEyIGRhdGFzZXQiKQpzczJfbXV0YW50c19maW5hbApwYXN0ZSgiVGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBTbWFydC1zZXEyIGRhdGFzZXQgaXM6IikKdGFibGUoc3MyX211dGFudHNfZmluYWxAbWV0YS5kYXRhJGdlbm90eXBlKQpgYGAKCiMgMy4gTWVyZ2luZyB0aGUgU21hcnQtc2VxMiBhbmQgMTBYIERhdGEgey50YWJzZXR9CgojIyMgUHJlcGFyZSBkYXRhCgpgYGB7ciBpbnRlZ3JhdGlvbiAxMHggc2V0dXB9CiMjIGV4dHJhY3QgMTB4IGRhdGEKdGVueF81a19jb3VudHMgPC0gYXMubWF0cml4KHBiX3NleF9maWx0ZXJlZEBhc3NheXMkUk5BQGNvdW50cykKdGVueF81a19waGVubyA8LSBwYl9zZXhfZmlsdGVyZWRAbWV0YS5kYXRhCgojIyBDcmVhdGUgZnJlc2ggb2JqZWN0CnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gdGVueF81a19jb3VudHMsIG1ldGEuZGF0YSA9IHRlbnhfNWtfcGhlbm8sIG1pbi5jZWxscyA9IDAsIG1pbi5mZWF0dXJlcyA9IDAsIHByb2plY3QgPSAiR0NTS08iKQoKIyMgYWRkIGV4cGVyaW1lbnQgbWV0YSBkYXRhCnRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZUBtZXRhLmRhdGEkZXhwZXJpbWVudCA8LSAidGVueF81ayIKCiMjIGluc3BlY3QKdGVueF81a19jb3VudHNfdG9faW50ZWdyYXRlCmBgYAoKV2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIG11dGFudCBkYXRhIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgMTBYIGRhdGEuIHRoZSAxMFggZGF0YSBoYXMgZmV3ZXIgZ2VuZXMgcmVwcmVzZW50ZWQgc28gd2UgbmVlZCB0byBmaW5kIHRoZSBpbnRlcnNlY3Qgb2YgdGhlIHR3byBiZWZvcmUgaW50ZWdyYXRpb24uCmBgYHtyIGludGVncmF0aW9uIHNzMiBzZXR1cH0KIyMgZXh0cmFjdCBTUzIgZGF0YSAKbXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24gPC0gYXMubWF0cml4KHNzMl9tdXRhbnRzX2ZpbmFsQGFzc2F5cyRSTkFAY291bnRzKQptdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uIDwtIHNzMl9tdXRhbnRzX2ZpbmFsQG1ldGEuZGF0YQoKIyMgY2hhbmdlIGNvdW50cyBzbyB0aGUgOnJSTkEgYW5kIDp0Uk5BIGFyZSBub3QgdGhlcmU6CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCI6bmNSTkEiLCAiIiwgZ3N1YigiOnJSTkEiLCAiIiwgZ3N1YigiOnRSTkEiLCAiIiwgcm93bmFtZXMobXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pKSkpCgojIyBjaGFuZ2UgdGhlIGdlbmUgbmFtZXMgc28gdGhhdCB0aGV5IGFyZSAtIHJhdGhlciB0aGFuIF86CnJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSA8LSBnc3ViKCJfIiwgIi0iLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpCgojIyBjYWxjdWxhdGUgaG93IG1hbnkgb2YgdGhlIGdlbmVzIG92ZXJsYXAgLSAxMHggZG9lcyBzdGFydCBvdXQgd2l0aCA1MDk4IHZzIDUyNDUKZ2VuZXNfaW5fdGVueF9kYXRhc2V0IDwtIGludGVyc2VjdChyb3duYW1lcyh0ZW54XzVrX2NvdW50cyksIHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSkKIyMgcHJpbnQgbnVtYmVyIG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCiMjIHN1YnNldCB0aGUgbXV0YW50IGNvdW50cyB0byBjb250YWluIG9ubHkgMTB4IGdlbmVzCm11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uIDwtIG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uW3doaWNoKHJvd25hbWVzKG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uKSAlaW4lIGdlbmVzX2luX3RlbnhfZGF0YXNldCksIF0KIyMgcHJpbnQgcmVzdWx0IG9mIGdlbmVzIHRoYXQgb3ZlcmxhcApkaW0obXV0YW50X2NvdW50c19mb3JfaW50ZWdyYXRpb24pCgojIyBtYWtlIFNldXJhdCBvYmplY3Q6CkdDU0tPX211dGFudHMgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG11dGFudF9jb3VudHNfZm9yX2ludGVncmF0aW9uLCBtZXRhLmRhdGEgPSBtdXRhbnRfcGhlbm9fZm9yX2ludGVncmF0aW9uLCBtaW4uY2VsbHMgPSAwLCBtaW4uZmVhdHVyZXMgPSAwLCBwcm9qZWN0ID0gIkdDU0tPIikKCiMjIGFkZCBleHBlcmltZW50IG1ldGEgZGF0YQpHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRleHBlcmltZW50IDwtICJtdXRhbnRzIgoKIyMgaW5zcGVjdApHQ1NLT19tdXRhbnRzCmBgYAoKYGBge3J9CiMjIGRvdWJsZSBjaGVjayB0aGF0IHRoaXMgaXMgdGhlIHNhbWUgbnVtYmVyIG9mIGdlbmVzCiMjIHN1YnNldCBjb3VudHMgc28gdGhhdCBvbmx5IGdlbmVzIHJlcHJlc2VudGVkIGluIHRoZSBvdGhlciB0d28gb2JqZWN0cyBhcmUgdGhlcmU6Cmxlbmd0aChpbnRlcnNlY3Qocm93bmFtZXModGVueF81a19jb3VudHMpLCByb3duYW1lcyhtdXRhbnRfY291bnRzX2Zvcl9pbnRlZ3JhdGlvbikpKQpgYGAKCklNUE9SVEFOVCAtIHRoaXMgbmV4dCBzdGVwIGlzIGRpZmZlcmVudCB0byBHQ1NLT19tZXJnZSBhcyBpdCBzdWJzZXRzIHRoZSBzbWFydC1zZXEyIGRhdGEgaW50byB3aWxkLXR5cGUgb25seS4gCmBgYHtyfQojIyBzdWJzZXQgd3Qgb24gc3MyIGRhdGE6CnNzMl93dF9jZWxscyA8LSByb3duYW1lcyhHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YVtHQ1NLT19tdXRhbnRzQG1ldGEuZGF0YSRnZW5vdHlwZSA9PSAiV1QiLCBdKQpHQ1NLT19tdXRhbnRzX3d0b25seSA8LSBzdWJzZXQoR0NTS09fbXV0YW50cywgY2VsbHMgPSBzczJfd3RfY2VsbHMpCmBgYAoKY3JlYXRlIGxpc3QgYW5kIG5vcm1hbGlzZToKYGBge3IgaW50ZWdyYXRpb24gbm9ybWFsaXNlfQojIyBtYWtlIGxpc3QKdGVueC5qdXN0d3QubGlzdCA8LSBsaXN0KHRlbnhfNWtfY291bnRzX3RvX2ludGVncmF0ZSwgR0NTS09fbXV0YW50c193dG9ubHkpCgojIyBwcmVwYXJlIGRhdGEKZm9yIChpIGluIDE6bGVuZ3RoKHRlbnguanVzdHd0Lmxpc3QpKSB7CiAgICB0ZW54Lmp1c3R3dC5saXN0W1tpXV0gPC0gTm9ybWFsaXplRGF0YSh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHZlcmJvc2UgPSBGQUxTRSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyh0ZW54Lmp1c3R3dC5saXN0W1tpXV0sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgCiAgICAgICAgbmZlYXR1cmVzID0gMjAwMCwgdmVyYm9zZSA9IEZBTFNFKQogICAgYWxsLmdlbmVzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0Lmxpc3RbW2ldXSkKICAgIHRlbnguanVzdHd0Lmxpc3RbW2ldXSA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QubGlzdFtbaV1dLCBmZWF0dXJlcyA9IGFsbC5nZW5lcykKfQpgYGAKCiMjIyBJbnRlZ3JhdGUgb2JqZWN0cwoKYGBge3IgaW50ZWdyYXRpb259CiMjIEZpbmQgYW5jaG9ycwp0ZW54Lmp1c3R3dC5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSB0ZW54Lmp1c3R3dC5saXN0LCBkaW1zID0gMToyMSwgdmVyYm9zZSA9IEZBTFNFKQoKIyMgSW50ZWdyYXRlIGRhdGEKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IHRlbnguanVzdHd0LmFuY2hvcnMsIGRpbXMgPSAxOjIxLCB2ZXJib3NlID0gRkFMU0UsIGZlYXR1cmVzLnRvLmludGVncmF0ZSA9IGdlbmVzX2luX3RlbnhfZGF0YXNldCkKYGBgCgojIDQuIERpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiB7LnRhYnNldH0KCiMjIyBQQ0EKYGBge3IsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNX0KIyMgTWFrZSB0aGUgZGVmYXVsdCBhc3NheSBpbnRlZ3JhdGVkCkRlZmF1bHRBc3NheSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKSA8LSAiaW50ZWdyYXRlZCIKCiMjIFJ1biB0aGUgc3RhbmRhcmQgd29ya2Zsb3cgZm9yIHZpc3VhbGl6YXRpb24gYW5kIGNsdXN0ZXJpbmcKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBTY2FsZURhdGEodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgdmVyYm9zZSA9IEZBTFNFKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIFJ1blBDQSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBucGNzID0gMzAsIHZlcmJvc2UgPSBGQUxTRSkKCiMjIGluc3BlY3QgUENzCkVsYm93UGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBuZGltcyA9IDMwLCByZWR1Y3Rpb24gPSAicGNhIikKYGBgCgojIyMgT3B0aW1pc2VkIFVNQVAKQWZ0ZXIgb3B0aW1pc2F0aW9uLCB0aGUgZm9sbG93aW5nIFVNQVAgY2FuIGJlIGNhbGN1bGF0ZWQ6CmBgYHtyIHVtYXAgcnVuIDIsIGZpZy5oZWlnaHQgPSA3LCBmaWcud2lkdGggPSA3fQojIyBSdW4gb3B0aW1pc2VkIFVNQVAKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBSdW5VTUFQKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gMToxMCwgbi5uZWlnaGJvcnMgPSA1MCwgc2VlZC51c2UgPSAxMjM0LCBtaW4uZGlzdCA9IDAuNCwgcmVwdWxzaW9uLnN0cmVuZ3RoID0gMC4wMywgbG9jYWwuY29ubmVjdGl2aXR5ID0gMTUwKQpgYGAKCmBgYHtyIHVtYXAgdmlzdWFsaXNlIDJ9CiMjIHBsb3QKZHAxIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IEZBTFNFLCBwdC5zaXplID0gMC4wNSwgZGltcyA9IGMoMSwyKSwgc3BsaXQuYnkgPSAiZXhwZXJpbWVudCIpICsgCiAgIyMgZml4IHRoZSBheGlzCiAgY29vcmRfZml4ZWQoKSAjKyAKICAjIyByZXZlcnNlIHRoZSBzY2FsZQogICNzY2FsZV95X3JldmVyc2UoKQoKIyMgdmlldwpkcDEKYGBgCgpNYWtlIGZpbmFsIHBsb3RzOgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KCiMjIHNwbGl0IHNldXJhdCBvYmplY3QgdXAKb2IubGlzdCA8LSBTcGxpdE9iamVjdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzcGxpdC5ieSA9ICJleHBlcmltZW50IikKCiMjIG1ha2UgcGxvdHMgZm9yIGVhY2ggb2JqZWN0CnBsb3QubGlzdCA8LSBsYXBwbHkoWCA9IG9iLmxpc3QsIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgIERpbVBsb3QoeCwgZGltcyA9IGMoMSwyKSwgcHQuc2l6ZSA9IDEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKQp9KQoKY29tcG9zaXRpb25fdW1hcF8xMHggPC0gcGxvdC5saXN0JGB0ZW54XzVrYCArIAogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKHJlcGxpY2F0ZSg0NSwgIiM5OTk5OTkiKSkpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIjEweCAod2lsZC10eXBlKSIpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkKCmNvbXBvc2l0aW9uX3VtYXBfc3MyIDwtIHBsb3QubGlzdCRtdXRhbnRzICsKICBjb29yZF9maXhlZCgpICsKICB0aGVtZV92b2lkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhyZXBsaWNhdGUoNDYsICIjOTk5OTk5IikpKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTbWFydC1zZXEyICh3aWxkLXR5cGUpIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKQoKY29tcG9zaXRpb25fdW1hcCA8LSBjb21wb3NpdGlvbl91bWFwXzEweCArIGNvbXBvc2l0aW9uX3VtYXBfc3MyIAoKY29tcG9zaXRpb25fdW1hcApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9jb21wb3NpdGlvbl91bWFwLnBuZyIsIHBsb3QgPSBjb21wb3NpdGlvbl91bWFwLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjAsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCmBgYHtyfQojIyBtYWtlIHBsb3RzCiMjIGhvbyBkYXRhc2V0IGNvcnJlbGF0aW9uClVNQVBfaG9vIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcHQuc2l6ZSA9IDAuMSwgZ3JvdXAuYnkgPSAiUHJlZGljdGlvbi5TcGVhcm1hbi4iLCBkaW1zID0gYygxLDIpKSArCiAgY29vcmRfZml4ZWQoKSArIAogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJIb28gUHJlZGljdGVkIFRpbWVwb2ludCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBpbmZlcm5vKDEyKSkgICsKICBsYWJzKGNvbG91ciA9ICJob3VyIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKIyMgYXAyZyB0aW1lY291cnNlIGluIHRoaXMgcGFwZXIgY29ycmVsYXRpb24KVU1BUF9rYXNpYSA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIHB0LnNpemUgPSAwLjEsIGdyb3VwLmJ5ID0gIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIiwgZGltcyA9IGMoMSwyKSkgKwogIGNvb3JkX2ZpeGVkKCkgKyAKICB0aGVtZV92b2lkKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiQVAyRyBUaW1lY291cnNlIFByZWRpY3RlZCBUaW1lcG9pbnQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gaW5mZXJubygxMCkpICArCiAgbGFicyhjb2xvdXIgPSAiaG91ciIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkKCiMjIGNvbWJpbmUKdW1hcF9idWxrIDwtIHdyYXBfcGxvdHMoVU1BUF9ob28sIFVNQVBfa2FzaWEsIG5jb2wgPSAyKQoKIyMgcHJpbnQKdW1hcF9idWxrCmBgYAoKIyMgTUNBIE1hcHBpbmcKCiMjIEJ1aWxkIHRoZSBpbmRleAoKYGBge3J9CiMjIGxvYWQgaW4gbWNhIGRhdGEKY291bnRzIDwtIHJlYWQuY3N2KCIuLi9kYXRhL1JlZmVyZW5jZS9zY21hcC9hbGxwYjEweF9jb3VudHMuY3N2Iiwgcm93Lm5hbWVzID0gMSkKcGhlbm8gPC0gcmVhZC5jc3YoIi4uL2RhdGEvUmVmZXJlbmNlL3NjbWFwL2FsbHBiMTB4X3BoZW5vLmNzdiIpCgojIyBjaGFuZ2UgZGFzaApyb3duYW1lcyhjb3VudHMpIDwtIGdzdWIoIl8iLCAiLSIsIHJvd25hbWVzKGNvdW50cykpCgojIyBsb2FkIE1DQSBwYWwKbWNhX2NvbG9ycyA8LSBjKCI2Ij0iIzc4QzY3OSIsCiAgICAgICAgICAgICIyIj0iI0QxRUM5RiIsCiAgICAgICAgICAgICIwIj0iI0ZFQjI0QyIsCiAgICAgICAgICAgICIxIj0iI0Y0Q0Y2MyIsCiAgICAgICAgICAgICIzIj0iI0ZFRUVBQSIsCiAgICAgICAgICAgICI0Ij0iIzg1QjFEMyIsCiAgICAgICAgICAgICI3Ij0iIzllY2FlMSIsCiAgICAgICAgICAgICI1Ij0iI0M5RThGMSIsCiAgICAgICAgICAgICJNIj0gIiNCN0I3RDgiLAogICAgICAgICAgICAiRiI9IiM5Qzk2QzYiLAogICAgICAgICAgICAidW5hc3NpZ25lZCI9ImRhcmtncmV5IikKCiMjIHBsb3QKZ2dwbG90KHBoZW5vLCBhZXMoeD1QQzJfM2QsIHkgPSBQQzNfM2QsIGNvbG91cj1hYnNjbHVzdDMpKSArIAogIGdlb21fcG9pbnQoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbWNhX2NvbG9ycywgbGFiZWxzID0gKGMoIjAgLSBlYXJseSB0cm9waCIsICIxIC0gbWlkIHRyb3BoIiwiMiAtIGxhdGUgcmluZyIsICIzIC0gbGF0ZSB0cm9waCIsIjQgLSBlYXJseSBzY2hpem9udCIsICI1IC0gbGF0ZSBzY2hpem9udCIsICI2IC0gZWFybHkgcmluZyIsIjcgLSBtaWQgc2NoaXpvbnQiLCAiZmVtYWxlIiwgIm1hbGUiLCAidW5hc3NpZ25lZCIpKSkKYGBgCgpgYGB7cn0KIyMjTWFraW5nIGFuIG9ydGhvbG9nIHJlZmVyZW5jZSBpbmRleAoKIyMgbG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShzY21hcCkKbGlicmFyeShTaW5nbGVDZWxsRXhwZXJpbWVudCkKCiNwcmVwIHRoZSBTQ0UsIGlmIHdhcyBvcmlnaW5hbGx5IGEgU3VlcmF0IG9iamVjdCBuZWVkIHRoZSBkZnMgdG8gYmUgcmVndWxhciBtYXRyaWNlcwojcGJfZmlsdGVyZWRfc2NlX29ydGggPC0gcGJfZmlsdGVyZWRfc2NlX29ydGhbLCBjb2xEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRhYnNjbHVzdDMgIT0gIjgiXQojc2NlIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoCiNwY2EgPC0gcGxvdFBDQShzY2UpCiNwY3MgPC0gcGNhJGRhdGEKI3RhYmxlKHJvd25hbWVzKHBjcyk9PWNvbG5hbWVzKHNjZSkpCiNjb2xEYXRhKHNjZSkgPC0gY2JpbmQoY29sRGF0YShzY2UpLCBwY3MpCiNyb3dEYXRhKHNjZSkkZmVhdHVyZV9zeW1ib2wgPC0gcm93RGF0YShzY2UpJGdlbmUKc2NlIDwtIFNpbmdsZUNlbGxFeHBlcmltZW50KGxpc3QoY291bnRzPWNvdW50cyksCiAgICBjb2xEYXRhPURhdGFGcmFtZShsYWJlbD1waGVubyksCiAgICByb3dEYXRhPURhdGFGcmFtZShmZWF0dXJlX3N5bWJvbD1yb3duYW1lcyhjb3VudHMpKSkKc2NlCmNvdW50c18xIDwtIGFzc2F5KHNjZSwgImNvdW50cyIpCmxpYnNpemVzIDwtIGNvbFN1bXMoY291bnRzXzEpCnNpemUuZmFjdG9ycyA8LSBsaWJzaXplcy9tZWFuKGxpYnNpemVzKQpsb2djb3VudHMoc2NlKSA8LSBsb2cyKHQodChjb3VudHNfMSkvc2l6ZS5mYWN0b3JzKSArIDEpCiNjb3VudHMoc2NlKSA8LSBhcy5tYXRyaXgoY291bnRzKHNjZSkpCiNsb2djb3VudHMoc2NlKSA8LSBhcy5tYXRyaXgobG9nY291bnRzKHNjZSkpCiMgcmVtb3ZlIGZlYXR1cmVzIHdpdGggZHVwbGljYXRlZCBuYW1lcwpzY2UgPC0gc2NlWyFkdXBsaWNhdGVkKHJvd25hbWVzKHNjZSkpLCBdCgojYnVpbGQgc2NtYXAtY2VsbCByZWZlcmVuY2UgaW5kZXgsIHNhdmUgdGhpcyByZHMKc2NlIDwtIHNlbGVjdEZlYXR1cmVzKHNjZSwgc3VwcHJlc3NfcGxvdCA9IEZBTFNFLCBuX2ZlYXR1cmVzID0gNTAwKQp0YWJsZShyb3dEYXRhKHNjZSkkc2NtYXBfZmVhdHVyZXMpCgpzZXQuc2VlZCgxKQpzY2UgPC0gaW5kZXhDZWxsKHNjZSkKbmFtZXMobWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4KQpsZW5ndGgobWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkcykKZGltKG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCRzdWJjZW50cm9pZHNbWzFdXSkKbWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkc1tbMV1dWywxOjVdCmRpbShtZXRhZGF0YShzY2UpJHNjbWFwX2NlbGxfaW5kZXgkc3ViY2x1c3RlcnMpCgojc2F2ZVJEUyhwYl9maWx0ZXJlZF9zY2Vfb3J0aCwgZmlsZT0icGJfZmlsdGVyZWRfc2NlX29ydGhpbmRleF8yMDE4MTEwOS5yZHMiKQpgYGAKCiMjIE1hcCB0byB0aGUgaW5kZXgKCmBgYHtyfQojIyBjb252ZXJ0IHNldXJhdCBvYmplY3QgYWJvdmUgaW50byBzY2UgZm9yIHRoaXMKcGZfZmllbGRfY291bnRzIDwtIGFzLm1hdHJpeCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQGFzc2F5cyRSTkFAZGF0YSkKcGZfZmllbGRfcGhlbm8gPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEKCiNwcmVwIHRoZSBTQ0UsIGlmIHdhcyBvcmlnaW5hbGx5IGEgU3VlcmF0IG9iamVjdCBuZWVkIHRoZSBkZnMgdG8gYmUgcmVndWxhciBtYXRyaWNlcwojcGJfZmlsdGVyZWRfc2NlX29ydGggPC0gcGJfZmlsdGVyZWRfc2NlX29ydGhbLCBjb2xEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRhYnNjbHVzdDMgIT0gIjgiXQojc2NlIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoCiNwY2EgPC0gcGxvdFBDQShzY2UpCiNwY3MgPC0gcGNhJGRhdGEKI3RhYmxlKHJvd25hbWVzKHBjcyk9PWNvbG5hbWVzKHNjZSkpCiNjb2xEYXRhKHNjZSkgPC0gY2JpbmQoY29sRGF0YShzY2UpLCBwY3MpCiNyb3dEYXRhKHNjZSkkZmVhdHVyZV9zeW1ib2wgPC0gcm93RGF0YShzY2UpJGdlbmUKcGZfbGl2ZV9maWVsZC5zY2Uub3J0aCA8LSBTaW5nbGVDZWxsRXhwZXJpbWVudChsaXN0KGNvdW50cz1wZl9maWVsZF9jb3VudHMpLAogICAgY29sRGF0YT1EYXRhRnJhbWUobGFiZWw9cGZfZmllbGRfcGhlbm8pLAogICAgcm93RGF0YT1EYXRhRnJhbWUoZmVhdHVyZV9zeW1ib2w9cm93bmFtZXMocGZfZmllbGRfY291bnRzKSkpCnBmX2xpdmVfZmllbGQuc2NlLm9ydGgKY291bnRzXzEgPC0gYXNzYXkocGZfbGl2ZV9maWVsZC5zY2Uub3J0aCwgImNvdW50cyIpCmxpYnNpemVzIDwtIGNvbFN1bXMoY291bnRzXzEpCnNpemUuZmFjdG9ycyA8LSBsaWJzaXplcy9tZWFuKGxpYnNpemVzKQpsb2djb3VudHMocGZfbGl2ZV9maWVsZC5zY2Uub3J0aCkgPC0gbG9nMih0KHQoY291bnRzXzEpL3NpemUuZmFjdG9ycykgKyAxKQoKCiNQcm9qZWN0IHF1ZXJ5IGRhdGEgc2V0IG9udG8gY2VsbCBpbmRleApzY21hcENlbGxfcmVzdWx0cyA8LSBzY21hcENlbGwoCiAgcGZfbGl2ZV9maWVsZC5zY2Uub3J0aCwgCiAgbGlzdChtY2EgPSBtZXRhZGF0YShzY2UpJHNjbWFwX2NlbGxfaW5kZXgKICApCikKCiMjTG9vayBpbnRvIHRoZSByZXN1bHRzCiMgRm9yIGVhY2ggZGF0YXNldCB0aGVyZSBhcmUgdHdvIG1hdHJpY2llcy4gY2VsbHMgbWF0cml4IGNvbnRhaW5zIHRoZSB0b3AgMTAgKHNjbWFwIGRlZmF1bHQpIGNlbGwgSURzIG9mIHRoZSBjZWxscyBvZiB0aGUgcmVmZXJlbmNlIGRhdGFzZXQgdGhhdCBhIGdpdmVuIGNlbGwgb2YgdGhlIHByb2plY3Rpb24gZGF0YXNldCBpcyBjbG9zZXN0IHRvOgojICAgCiMgICBHaXZlIGFzc2lnbm1lbnRzIGluIHR3byB3YXlzOgojICAgMS4gVGFrZSB0aGUgdG9wIGNlbGwgYXNzaWdubWVudCBhYnMgY2x1c3QsIGlmIGNvc2luZSBzaW1pbGFyaXR5IGlzIGxlc3MgdGhhbiAwLjQgKG9yIGFkanVzdCBpZiBuZWVkZWQpIG1hcmsgYXMgdW5hc3NpZ25lZAojIDIuIEZvciB0aGUgdG9wIDMgbmVhcmVzdCBuZWlnaGJvcnMsIGdldCBhIG1lYW4gb2YgdGhlIFBDQSBjb29yZGluYXRlcyBhbmQgc25hcCB0byB0aGUgbmVhcmVzdCBjZWxsIG9mIHRob3NlIGNvb3JkaW5hdGVzLiBJZiBhbnkgb2YgdGhlIHRvcCB0aHJlZSBjZWxscyBhcmUgc2ltIGJlbG93IDAuNCB0aGVuIG1hcmsgYXMgdW5hc3NpZ25lZC4KCgojI1RvcCBjZWxsIGFzc2lnbm1lbnQgbWV0aG9kCnNjbWFwQ2VsbF9yZXN1bHRzJG1jYSRjZWxsc1ssIDE6M10KZ2V0Y2VsbHMgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkbWNhJGNlbGxzWzEsIF0KY2RzY2UgPC0gY29sRGF0YShzY2UpW2dldGNlbGxzLCBdCnRvcHNpbSA8LSBzY21hcENlbGxfcmVzdWx0cyRtY2Ekc2ltaWxhcml0aWVzWzEsIF0KCnBmX2xpdmVfZmllbGQuc2NlLm9ydGgkdG9wY2VsbCA8LSBjZHNjZSRsYWJlbC5zYW1wbGVfaWQKcGZfbGl2ZV9maWVsZC5zY2Uub3J0aCR0b3BjZWxsX2FjIDwtIGNkc2NlJGxhYmVsLmFic2NsdXN0MwpwZl9saXZlX2ZpZWxkLnNjZS5vcnRoJGluZGV4UEMxIDwtIGNkc2NlJGxhYmVsLlBDMQpwZl9saXZlX2ZpZWxkLnNjZS5vcnRoJGluZGV4UEMyIDwtIGNkc2NlJGxhYmVsLlBDMgojcGZfbGl2ZV9maWVsZC5zY2Uub3J0aCRwYnB0IDwtIGNkc2NlJHBzZXVkb3RpbWUKI3BmX2xpdmVfZmllbGQuc2NlLm9ydGgkcGJidWxrIDwtIGNkc2NlJGJ1bGsKcGZfbGl2ZV9maWVsZC5zY2Uub3J0aCR0b3BjZWxsX3NwIDwtIHBmX2xpdmVfZmllbGQuc2NlLm9ydGgkdG9wY2VsbF9hYwpwZl9saXZlX2ZpZWxkLnNjZS5vcnRoJHRvcHNpbSA8LSB0b3BzaW0KcGZfbGl2ZV9maWVsZC5zY2Uub3J0aCR0b3BjZWxsX3NwW3BmX2xpdmVfZmllbGQuc2NlLm9ydGgkdG9wc2ltIDwgMC4zXSA8LSAidW5hc3NpZ25lZCIKdGFibGUocGZfbGl2ZV9maWVsZC5zY2Uub3J0aCR0b3BjZWxsX3NwKQpgYGAKCmFkZCB0aGVzZSBtZXRyaWNzIGJhY2sgaW50byB0aGUgb2JqZWN0IAoKYGBge3J9CiMjIGFkZCB0aGUgbWV0YSBkYXRhIGZyb20gc2NtYXAgdG8gdGhlIG9iamVjdAojIGxpdmUKIyMgZXh0cmFjdApkZl9wbG90X2xpdmUgPC0gZGF0YS5mcmFtZSh0b3BjZWxsX3NwID0gY29sRGF0YShwZl9saXZlX2ZpZWxkLnNjZS5vcnRoKSR0b3BjZWxsX3NwLCB0b3BzaW0gPSBjb2xEYXRhKHBmX2xpdmVfZmllbGQuc2NlLm9ydGgpJHRvcHNpbSwgcm93Lm5hbWVzID0gcm93bmFtZXMoY29sRGF0YShwZl9saXZlX2ZpZWxkLnNjZS5vcnRoKSkpCgojIyBhZGQgdG8gb2JqZWN0CnRlbnguanVzdHd0LmludGVncmF0ZWQgPC0gQWRkTWV0YURhdGEoCiAgb2JqZWN0ID0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZCwKICBtZXRhZGF0YSA9IGRmX3Bsb3RfbGl2ZSwKICBjb2wubmFtZSA9IGMoJ21jYV90b3BjZWxsX3NwJywgJ21jYV90b3BzaW0nKQopCgojIyBuZWVkIHRvIGZpeCB0aGUgTkEgaW4gdG9wY2VsbF9zcAojIFVuLWZhY3Rvcml6ZSAoYXMubnVtZXJpYyBjYW4gYmUgdXNlIGZvciBudW1lcmljIHZhbHVlcykKIyAgICAgICAgICAgICAgKGFzLnZlY3RvciAgY2FuIGJlIHVzZSBmb3Igb2JqZWN0cyAtIG5vdCB0ZXN0ZWQpCnRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJG1jYV90b3BjZWxsX3NwIDwtIGFzLmNoYXJhY3Rlcih0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRtY2FfdG9wY2VsbF9zcCkKIyMgYWRkIHVuYXNzaWduZWQKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkbWNhX3RvcGNlbGxfc3BbaXMubmEodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkbWNhX3RvcGNlbGxfc3ApXSA8LSAidW5hc3NpZ25lZCIKIyBSZS1mYWN0b3JpemUgd2l0aCB0aGUgYXMuZmFjdG9yIGZ1bmN0aW9uIG9yIHNpbXBsZSBmYWN0b3IoZml4ZWQkVHlwZSkKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkbWNhX3RvcGNlbGxfc3AgPC0gYXMuZmFjdG9yKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJG1jYV90b3BjZWxsX3NwKQojIyBjaGVjawp0YWJsZSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRtY2FfdG9wY2VsbF9zcCkKYGBgCgpgYGB7cn0KIyMgcmVvcmRlciBsZXZlbHMKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkbWNhX3RvcGNlbGxfc3AgPC0gZmFjdG9yKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJG1jYV90b3BjZWxsX3NwLCBsZXZlbHMgPSByZXYoYygiTSIsICJGIiwgIjUiLCAiNyIsICI0IiwgIjMiLCAiMSIsICIwIiwgIjIiLCAiNiIpKSkKClVNQVBfbWNhIDwtIERpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcHQuc2l6ZSA9IDAuMSwgZ3JvdXAuYnkgPSAibWNhX3RvcGNlbGxfc3AiLCBkaW1zID0gYygxLDIpKSArCiAgY29vcmRfZml4ZWQoKSArIAogIHRoZW1lX3ZvaWQoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJNQ0EgUHJlZGljdGVkIENlbGwgVHlwZSIpLCBjb2xvdXIgPSAiTUNBIENlbGwgVHlwZSIpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbWNhX2NvbG9ycywgbGFiZWxzID0gKGMoIjYgLSBlYXJseSByaW5nIiwgIjIgLSBsYXRlIHJpbmciLCAiMCAtIGVhcmx5IHRyb3BoIiwgIjEgLSBtaWQgdHJvcGgiLCAiMyAtIGxhdGUgdHJvcGgiLCAiNCAtIGVhcmx5IHNjaGl6b250IiwgIjcgLSBtaWQgc2NoaXpvbnQiLCAiNSAtIGxhdGUgc2NoaXpvbnQiLCAiZmVtYWxlIiwgIm1hbGUiKSkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTUpKQoKVU1BUF9tY2EKYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvVU1BUF9tY2EucG5nIiwgcGxvdCA9IFVNQVBfbWNhLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAxNSwgaGVpZ2h0ID0gMTUsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMgNS4gQ2x1c3RlcmluZyB7LnRhYnNldH0gCgojIyMgR2VuZXJhdGUgY2x1c3RlcnMKCmBgYHtyfQojIyBnZW5lcmF0ZSBuZXcgY2x1c3RlcnMgYXQgbG93IHJlc29sdXRpb24KdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBGaW5kTmVpZ2hib3JzKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSAxOjE5LCByZWR1Y3Rpb24gPSAicGNhIikKdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBGaW5kQ2x1c3RlcnModGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcmVzb2x1dGlvbiA9IDIsIHJhbmRvbS5zZWVkID0gNDIsIGFsZ29yaXRobSA9IDIpCmBgYAoKIyMjIHZpc3VhbGlzZSBjbHVzdGVycwoKYGBge3J9CkRpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFLCByZXBlbCA9IEZBTFNFLCBsYWJlbCA9IFRSVUUpCmBgYAoKTWFrZSBpbmRpdmlkdWFsIHBsb3RzIGhpZ2hsaWdodGluZyB3aGVyZSBjZWxscyBpbiBlYWNoIGNsdXN0ZXIgZmFsbApgYGB7ciwgZWNobyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIyBmb3IgbG9vcCB3aGljaCB0YWtlcyBlYWNoIGNsdXN0ZXIgYW5kIG1ha2VzIGEgbGlzdCBvZiBjZWxscyBhbmQgdGhlbiBwbG90cyBhIGhpZ2hsaWdodGVkIHBsb3QgYW5kIGFkZHMgaXQgdG8gYSBsaXN0CgojIyBtYWtlIGEgYmxhbmsgbGlzdApsaXN0X1VNQVBzX2J5X2NsdXN0ZXIgPC0gdmVjdG9yKG1vZGUgPSAibGlzdCIsIGxlbmd0aCA9IGxlbmd0aChsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIpKSkKCiMjIGZvciBsb29wCmZvcihpIGluIHNlcV9hbG9uZyhsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkaW50ZWdyYXRlZF9zbm5fcmVzLjIpKSl7CiAgIyMgbWFrZSBhIGxpc3Qgb2YgY2VsbHMKICBsaXN0X29mX2NlbGxzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhW3doaWNoKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJGludGVncmF0ZWRfc25uX3Jlcy4yID09IGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMilbaV0pLCBdKQogIHVtYXBfcGxvdCA8LSBEaW1QbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGxhYmVsID0gRkFMU0UsIHJlcGVsID0gVFJVRSwgcHQuc2l6ZSA9IDAuMSwgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdF9vZl9jZWxscywgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiKSArCiAgICAjIyBmaXggY29vcmRpbmF0ZXMKICAgIGNvb3JkX2ZpeGVkKCkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiNEM0QzRDMiLCAiIzFEMTU2NCIpKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiY2x1c3RlciIsIGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMilbaV0pKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiAgIyMgYWRkIHRvIHRoZSBsaXN0CiAgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1tpXV0gPC0gdW1hcF9wbG90Cn0KCiMjIGNoZWNrIG51bWJlciBvZiBjbHVzdGVycwpsZW5ndGgobGlzdF9VTUFQc19ieV9jbHVzdGVyKQpgYGAKCnBsb3QKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMjIHRoaXMgZnVuY3Rpb24gd3JpdGVzIHRoZSBuZXh0IGJpdCBvZiBjb2RlIGZvciB5b3UKIyMgcHV0IGl0IGludG8gdGhlIGNvbnNvbGUgYW5kIHBhc3RlIHRoZSByZXNwb25zZQojcGxvdHkgPC0gYygpCiNmb3IoaSBpbiBzZXFfYWxvbmcobGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycykpKXsKIyAgcGxvdHkgPC0gcGFzdGUwKHBsb3R5LCAibGlzdF9VTUFQc19ieV9jbHVzdGVyW1siLCBpLCAiXV0iLCAiICsgIikKI30KCiMjIHBsb3QKbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzJdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbM11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s0XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzVdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s3XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzhdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxMF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxMV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxM11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxNF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxNV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxNl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxN11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxOF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxOV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syMF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syMV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syM11dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syNF1dCmBgYAoKIyMjIEZpbmQgTWFya2VycwoKYGBge3J9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1ENCAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENSAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQzCiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCkRlZmF1bHRBc3NheSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKSA8LSAiUk5BIgojIGZpbmQgbWFya2VycyBmb3IgZXZlcnkgY2x1c3RlciBjb21wYXJlZCB0byBhbGwgcmVtYWluaW5nIGNlbGxzLCByZXBvcnQgb25seSB0aGUgcG9zaXRpdmUgb25lcwpwYi5tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKHRlbnguanVzdHd0LmludGVncmF0ZWQsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIGxvZ2ZjLnRocmVzaG9sZCA9IDAuMjUsIHRlc3QudXNlID0gIk1BU1QiKQpwYi5tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24obiA9IDUsIHd0ID0gYXZnX2xvZ0ZDKQpgYGAKCmBgYHtyfQptYXJrZXJzX2Fubm90YXRlZCA8LSBtZXJnZShwYi5tYXJrZXJzLCBnZW5lX2Fubm90YXRpb25zLCAgYnkueCA9ICJnZW5lIiwgYnkueSA9ICJHZW5lLklEIiwgYWxsID0gRkFMU0UpClZpZXcobWFya2Vyc19hbm5vdGF0ZWQpCmBgYAoKYGBge3IsIFIub3B0aW9ucyA9IGxpc3Qod2lkdGggPSAzMDApfQptYXJrZXJzX3N1YnNldCA8LSBwYi5tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24obiA9IDIwLCB3dCA9IGF2Z19sb2dGQykKbWFya2Vyc19zdWJzZXRfYW5ub3RhdGVkIDwtIG1lcmdlKG1hcmtlcnNfc3Vic2V0LCBnZW5lX2Fubm90YXRpb25zLCAgYnkueCA9ICJnZW5lIiwgYnkueSA9ICJHZW5lLklEIiwgYWxsID0gRkFMU0UpCm1hcmtlcnNfc3Vic2V0X2Fubm90YXRlZApWaWV3KG1hcmtlcnNfc3Vic2V0X2Fubm90YXRlZCkKYGBgCgpgYGB7cn0KVmlldyhtYXJrZXJzX2Fubm90YXRlZF9tdXRhbnQgPC0gbWFya2Vyc19hbm5vdGF0ZWRbd2hpY2gobWFya2Vyc19hbm5vdGF0ZWQkZ2VuZSAlaW4lIGxpc3Rfb2ZfbXV0YW50X2dlbmVzKSwgXSkKYGBgCgoKIyMjIHZpc3VhbGlzZSBtYXJrZXJzCgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyMgZ2V0IHRoZSB0b3AgMTAgZm9yIGVhY2ggY2x1c3Rlcgp0b3AxMCA8LSBwYi5tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24obiA9IDEwLCB3dCA9IGF2Z19sb2dGQykKCiMjIHNjYWxlIGRhdGEgaXMgbWlzc2luZyAtIGJ1dCBvcmlnaW5hbCBkZnMgaGF2ZSBzY2FsZS5kYXRhCiMgZGZfc2NhbGVkIDwtIGFzLm1hdHJpeCh0cmFuc2Zvcm0obWVyZ2UoYXMuZGF0YS5mcmFtZSh0ZW54Lmp1c3R3dC5saXN0W1sxXV1AYXNzYXlzJFJOQUBzY2FsZS5kYXRhKSwgYXMuZGF0YS5mcmFtZSh0ZW54Lmp1c3R3dC5saXN0W1syXV1AYXNzYXlzJFJOQUBzY2FsZS5kYXRhKSwgYnkgPSAwLCBhbGw9RkFMU0UpLCByb3cubmFtZXM9Um93Lm5hbWVzLCBSb3cubmFtZXM9TlVMTCkpCiMgdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBhc3NheXMkUk5BQHNjYWxlLmRhdGEgPC0gZGZfc2NhbGVkCgojIyBzY2FsZSBkYXRhIGluIFJOQSBzbG90CmFsbC5nZW5lcyA8LSByb3duYW1lcyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIFNjYWxlRGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCB2YXJzLnRvLnJlZ3Jlc3MgPSAnZXhwZXJpbWVudCcsIGZlYXR1cmVzID0gYWxsLmdlbmVzKQoKIyMgaGVhdG1hcApEb0hlYXRtYXAodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSB0b3AxMCRnZW5lKSArIE5vTGVnZW5kKCkKYGBgCgojIDYuIERlZmluZSBDbHVzdGVyIElkZW50aXRpZXMgey50YWJzZXR9IAoKIyMjIERvd25zYW1wbGluZwpgYGB7cn0KIyAjIyBjaGVjayBudW1iZXIgb2YgY2VsbHMgaW4gZWFjaCBjbHVzdGVyCiMgZGZfY2x1c3RlcnMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRpbnRlZ3JhdGVkX3Nubl9yZXMuMikpCiMgcGxvdChkZl9jbHVzdGVycykKIyAKIyAjIyBkb3duc2FtcGxlIHVzaW5nIGFwcHJvcHJpYXRlIG1ldHJpY3MKIyB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLmRvd25zYW1wbGVkIDwtIHN1YnNldCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkb3duc2FtcGxlID0gMTAwKQojICAgCiMgIyMgaW5zcGVjdCBwbG90CiMgRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5kb3duc2FtcGxlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTE0Mzc1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKIyAgIHRoZW1lX3ZvaWQoKSArIAojICAgbGFicyh0aXRsZSA9IHBhc3RlKCJBUDJHIChDb21taXRtZW50KSIpKSArIAojICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiMgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQpgYGAKCiMjIyBNYXJrZXIgR2VuZXMKCnVzZWZ1bCB0b29scyBmb3IgYWxsIHBsb3RzCmBgYHtyfQojIyBkZWZpbmUgbWFsZSBhbmQgZmVtYWxlIHN5bWJvbApmZW1hbGVfc3ltYm9sIDwtIGludFRvVXRmOCg5NzkyKQptYWxlX3N5bWJvbCA8LSBpbnRUb1V0ZjgoOTc5NCkKCiMjIGRlZmluZSBjb2xvdXIgcGFsCm1hcmtlcl9nZW5lX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRDNEM0QzIiwgIiMxRDE1NjQiKSkoNTApCmBgYAoKIyMjIyBFeHByZXNzaW9uIC0gY3V0b2ZmcyAtIHB1cnBsZQoKYGBge3IsIGZpZy5oZWlnaHQgPSAxNSwgZmlnLndpZHRoID0gMTV9CgptYXJrZXJfZ2VuZV9wbG90X0NDUDIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTMxOTUwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMoY2NwMil+KEZlbWFsZSkpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCm1hcmtlcl9nZW5lX3Bsb3RfTUcxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxNjEwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsKICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1nMSl+KE1hbGUpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCm1hcmtlcl9nZW5lX3Bsb3RfQVAyRyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhhcDJnKX4oQ29tbWl0bWVudCkpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCm1hcmtlcl9nZW5lX3Bsb3RfTVNQMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wODMxMDAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtc3AxKX4oU2NoaXpvbnQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01TUDggPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMjIwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMobXNwOCl+KEFzZXh1YWwpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X1NCUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMTMwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhTQlAxKX4oUmluZykpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9Ni4wKSwgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKCm1hcmtlcl9nZW5lX3Bsb3RfRkFNQiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wNzIyNjAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGZhbS1iMil+KFJpbmcpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X09SQzEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDYwMjAwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhvcmMxKX4oRE5BfnJlcGxpY2F0aW9uKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKbWFya2VyX2dlbmVfcGxvdF9DRFBLNSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTM1MTUwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGNkcGs1KX4oU2NoaXpvbnQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTYuMCksIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCgptYXJrZXJfZ2VuZV9wbG90X01DTTQgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTE0MTU2MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhtY200KX4oRE5BfnJlcGxpY2F0aW9uKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT02LjApLCBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQoKIyArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgojIyBwbG90CiMjIGNvd3Bsb3QgbWV0aG9kCm1hcmtlcl9nZW5lX3Bsb3RfYWxsIDwtIHBsb3RfZ3JpZChtYXJrZXJfZ2VuZV9wbG90X0ZBTUIsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQOCwgbWFya2VyX2dlbmVfcGxvdF9NU1AxLCBtYXJrZXJfZ2VuZV9wbG90X0FQMkcsIG1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiwgbWFya2VyX2dlbmVfcGxvdF9NRzEsIG1hcmtlcl9nZW5lX3Bsb3RfSFNQNzAsIG5yb3c9MykKCm1hcmtlcl9nZW5lX3Bsb3RfYWxsCmBgYAoKIyMjIE11dGFudCBHZW5lcwoKIyMjIyBFeHByZXNzaW9uIC0gd2l0aCBjdXRvZmZzCgpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyBQQkFOS0EtMTQxODEwMCAgICAgICAgR0NTS08tMTcgIEZEMyAgIAojIFBCQU5LQS0wMTAyNDAwICAgICAgICAgR0NTS08tMiAgTUQ0IAojIFBCQU5LQS0wNzE2NTAwICAgICAgICBHQ1NLTy0xOSAgTUQ1IAojIFBCQU5LQS0xNDM1MjAwICAgICAgICBHQ1NLTy0yMCAgRkQ0IAojIFBCQU5LQS0wOTAyMzAwICAgICAgICBHQ1NLTy0xMyAgRkQyCiMgUEJBTktBLTA0MTM0MDAgICAgR0NTS08tMTBfODIwICBNRDMKIyBQQkFOS0EtMDgyODAwMCAgICAgICAgIEdDU0tPLTMgIEdEMQojIFBCQU5LQS0xMzAyNzAwICAgICAgIEdDU0tPLW9vbSAgTUQxIAojIFBCQU5LQS0xNDQ3OTAwICAgICAgICBHQ1NLTy0yOSAgTUQyCiMgUEJBTktBLTE0NTQ4MDAgICAgICAgIEdDU0tPLTIxICBGRDEKIyBQQkFOS0EtMTE0NDgwMCAgICAgICAgR0NTS08tMjggIEZENQoKCm1hcmtlcl9nZW5lX3Bsb3RfZmQzIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTE0MTgxMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDMpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKICAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfbWQ0IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTAxMDI0MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1kNCkpKSArIAogICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkKICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfbWQ1IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA3MTY1MDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0LnNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICdzY2FsZS5kYXRhJykgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gZXhwcmVzc2lvbihpdGFsaWMobWQ1KSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMCwgMCwgMCksICJjbSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIsIGxhYmVscyA9IG51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuMywgYmFyaGVpZ2h0ID0gMy4wLCB0aXRsZSA9ICIiKSkgCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2ZkNCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM1MjAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhmZDQpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKSAKICAgICAgICAgICAgICAgICAgICAgICAjIyBhZGQgc2V4IHN5bWJvbHMKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfZmQyIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSAiUEJBTktBLTA5MDIzMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGZkMikpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgIyArIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0wNDEzNDAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gInEwNSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5jdXRvZmYgPSAicTk1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1kMykpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAjYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfZ2QxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMDgyODAwMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguY3V0b2ZmID0gInE5NSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbG90ID0gJ3NjYWxlLmRhdGEnKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBleHByZXNzaW9uKGl0YWxpYyhnZDEpKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAwLCAwLCAwKSwgImNtIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIiwgbGFiZWxzID0gbnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSAzLjAsIHRpdGxlID0gIiIpKQogICAgICAgICAgICAgICAgICAgICAgICMjIGFkZCBzZXggc3ltYm9scwogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogICAgICAgICAgICAgICAgICAgICAgICNhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF9tZDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTMwMjcwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmN1dG9mZiA9ICJxMDUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1kMSkpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X21kMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ0NzkwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQuZml4ZWQgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdC5zaXplID0gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKG1kMikpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X2ZkMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gIlBCQU5LQS0xNDU0ODAwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAicTA1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LmN1dG9mZiA9ICJxOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHQuc2l6ZSA9IDAuNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAnc2NhbGUuZGF0YScpICsgCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oaXRhbGljKGZkMSkpKSArIAogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiLCBsYWJlbHMgPSBudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjMsIGJhcmhlaWdodCA9IDMuMCwgdGl0bGUgPSAiIikpCiAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIHNleCBzeW1ib2xzCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgI2Fubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgojI29yaWdpbmFsIGxhYmVsOgojIGxhYnModGl0bGUgPSBwYXN0ZSgiKENDUDI7IEZlbWFsZSkiLCJcbiIsICJQQkFOS0FfMTMxOTUwMCIpKQojIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpCiMgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlIDwtIHdyYXBfcGxvdHMobWFya2VyX2dlbmVfcGxvdF9nZDEgLCBtYXJrZXJfZ2VuZV9wbG90X21kMSAsIG1hcmtlcl9nZW5lX3Bsb3RfbWQyICwgbWFya2VyX2dlbmVfcGxvdF9tZDMgLCBtYXJrZXJfZ2VuZV9wbG90X21kNCAsIG1hcmtlcl9nZW5lX3Bsb3RfbWQ1ICwgbWFya2VyX2dlbmVfcGxvdF9mZDEgLCBtYXJrZXJfZ2VuZV9wbG90X2ZkMiAsIG1hcmtlcl9nZW5lX3Bsb3RfZmQzICwgbWFya2VyX2dlbmVfcGxvdF9mZDQsIG5jb2wgPSA0KQogICAgICAgICAgIAojIyBwcmludAptdXRhbnRfZXhwcmVzc2lvbl9jb21wb3NpdGUKYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvQUxMX0NFTExTX3d0X2dlbmVfZXhwcmVzc2lvbi5wbmciLCBwbG90ID0gbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMSwgaGVpZ2h0ID0gMjkuNywgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1EMyAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQ1CiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCgptYXJrZXJfZ2VuZV9wbG90XzE3IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0MTgxMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wMTAyNDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzE5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MTY1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjAgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNTIwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wOTAyMzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzEwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTM0MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wODI4MDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X29vbSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xMzAyNzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCBtaW4uY3V0b2ZmID0gInExMCIsIG1heC5jdXRvZmYgPSAicTkwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzI5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0NDc5MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIG1pbi5jdXRvZmYgPSAicTEwIiwgbWF4LmN1dG9mZiA9ICJxOTAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ1NDgwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgbWluLmN1dG9mZiA9ICJxMTAiLCBtYXguY3V0b2ZmID0gInE5MCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlIDwtIHdyYXBfcGxvdHMobWFya2VyX2dlbmVfcGxvdF8xNyAsIG1hcmtlcl9nZW5lX3Bsb3RfMiAsIG1hcmtlcl9nZW5lX3Bsb3RfMTkgLCBtYXJrZXJfZ2VuZV9wbG90XzIwICwgbWFya2VyX2dlbmVfcGxvdF8xMyAsIG1hcmtlcl9nZW5lX3Bsb3RfMTAgLCBtYXJrZXJfZ2VuZV9wbG90XzMgLCBtYXJrZXJfZ2VuZV9wbG90X29vbSAsIG1hcmtlcl9nZW5lX3Bsb3RfMjkgLCBtYXJrZXJfZ2VuZV9wbG90XzIxICwgbmNvbCA9IDQpCiAgICAgICAgICAgCiMjIHByaW50Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZQpgYGAKCgoKIyA3LiBQc2V1ZG90aW1lIG9uIGFsbCBjZWxscyB7LnRhYnNldH0KCiMjIyBQc2V1ZG90aW1lIGNhbGN1bGF0aW9uCgpgYGB7cn0KIyMgZXh0cmFjdCBkYXRhIGZyb20gU2V1cmF0CnNldXJhdC5vYmplY3QuYWxsIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWQKIyBjb3VudHMKZGF0YSA8LSBhcyhhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKHNldXJhdC5vYmplY3QuYWxsLCBhc3NheSA9ICJpbnRlZ3JhdGVkIiwgc2xvdCA9ICJkYXRhIikpLCAnc3BhcnNlTWF0cml4JykKIyBtZXRhIGRhdGEKcGQgPC0gZGF0YS5mcmFtZShzZXVyYXQub2JqZWN0LmFsbEBtZXRhLmRhdGEpCgojIyBrZWVwIG9ubHkgdGhlIGNvbHVtbnMgdGhhdCBhcmUgcmVsZXZhbnQKI3BEYXRhIDwtIHBkICU+JSBzZWxlY3Qob3JpZy5pZGVudCwgbkNvdW50X1JOQSwgbkZlYXR1cmVfUk5BKQojIyBhZGQgZ2VuZSBzaG9ydCBuYW1lCmZEYXRhIDwtIGRhdGEuZnJhbWUoZ2VuZV9zaG9ydF9uYW1lID0gcm93Lm5hbWVzKGRhdGEpLCByb3cubmFtZXMgPSByb3cubmFtZXMoZGF0YSkpCgojIyBDb25zdHJ1Y3QgbW9ub2NsZSBjZHMKbW9ub2NsZS5vYmplY3QuYWxsIDwtIG5ld19jZWxsX2RhdGFfc2V0KGV4cHJlc3Npb25fZGF0YSA9IGRhdGEsIGNlbGxfbWV0YWRhdGEgPSBwZCwgZ2VuZV9tZXRhZGF0YSA9IGZEYXRhKQojIyBwcmVwcm9jZXNzCm1vbm9jbGUub2JqZWN0LmFsbCA9IHByZXByb2Nlc3NfY2RzKG1vbm9jbGUub2JqZWN0LmFsbCwgbnVtX2RpbSA9IDEwMCwgbm9ybV9tZXRob2QgPSAibm9uZSIpCiMjIHBsb3QgdmFyaWFuY2UgZXhwbGFpbmVkIHBsb3QKI3Bsb3RfcGNfdmFyaWFuY2VfZXhwbGFpbmVkKG1vbm9jbGUub2JqZWN0LmFsbCkKIyMgbWFrZSBtb25vY2xlIFVNQVAKI21vbm9jbGUub2JqZWN0LmFsbCA9IHJlZHVjZV9kaW1lbnNpb24obW9ub2NsZS5vYmplY3QuYWxsLCByZWR1Y3Rpb25fbWV0aG9kID0gIlVNQVAiLCBwcmVwcm9jZXNzX21ldGhvZCA9ICJQQ0EiLCB1bWFwLm1ldHJpYyA9ICJldWNsaWRlYW4iLCB1bWFwLm5fbmVpZ2hib3JzID0gMjAsIHVtYXAubWluX2Rpc3QgPSAwLjUsIHZlcmJvc2UgPSBGQUxTRSkKI3Bsb3RfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQoKIyMgYWRkIFVNQVAgZnJvbSBTZXVyYXQKbW9ub2NsZS5vYmplY3QuYWxsQGludF9jb2xEYXRhQGxpc3REYXRhJHJlZHVjZWREaW1zQGxpc3REYXRhW1siVU1BUCJdXSA8LXNldXJhdC5vYmplY3QuYWxsQHJlZHVjdGlvbnNbWyJ1bWFwIl1dQGNlbGwuZW1iZWRkaW5ncyAKcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwpCgojIyBjbHVzdGVyCm1vbm9jbGUub2JqZWN0LmFsbCA9IGNsdXN0ZXJfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQoKIyMgcGxvdCBjbHVzdGVycwpwbG90X2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCwgY29sb3JfY2VsbHNfYnk9InBhcnRpdGlvbiIsIGdyb3VwX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCAgeCA9IDEsIHkgPSAyKQoKIyMgcmVkdWNlIHBhcnRpdGlvbnMgdG8gMQptb25vY2xlLm9iamVjdC5hbGxAY2x1c3RlcnMkVU1BUCRwYXJ0aXRpb25zW21vbm9jbGUub2JqZWN0LmFsbEBjbHVzdGVycyRVTUFQJHBhcnRpdGlvbnMgPT0gIjIiXSA8LSAiMSIKCiNtYXAgcHNldWRvdGltZQptb25vY2xlLm9iamVjdC5hbGwgPSBsZWFybl9ncmFwaChtb25vY2xlLm9iamVjdC5hbGwsIGxlYXJuX2dyYXBoX2NvbnRyb2w9bGlzdChuY2VudGVyPTU1MCwgbWluaW1hbF9icmFuY2hfbGVuID0gMTUpLCB1c2VfcGFydGl0aW9uID0gRkFMU0UpCgpwbG90X2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCwgY29sb3JfY2VsbHNfYnk9InBhcnRpdGlvbiIsIGdyb3VwX2NlbGxzX2J5PSJwYXJ0aXRpb24iLCAgeCA9IDEsIHkgPSAyKQoKIyMgYSBoZWxwZXIgZnVuY3Rpb24gdG8gaWRlbnRpZnkgdGhlIHJvb3QgcHJpbmNpcGFsIHBvaW50czoKIyMgbWFrZSBjbHVzdGVyIDIgdGhlIHJvb3QKIyBnZXRfZWFybGllc3RfcHJpbmNpcGFsX25vZGUgPC0gZnVuY3Rpb24oY2RzLCB0aW1lX2Jpbj0iNyIpewojICAgY2VsbF9pZHMgPC0gd2hpY2goY29sRGF0YShjZHMpWywgInNldXJhdF9jbHVzdGVycyJdID09IHRpbWVfYmluKQojICAgY2xvc2VzdF92ZXJ0ZXggPC0KIyAgIGNkc0BwcmluY2lwYWxfZ3JhcGhfYXV4W1siVU1BUCJdXSRwcl9ncmFwaF9jZWxsX3Byb2pfY2xvc2VzdF92ZXJ0ZXgKIyAgIGNsb3Nlc3RfdmVydGV4IDwtIGFzLm1hdHJpeChjbG9zZXN0X3ZlcnRleFtjb2xuYW1lcyhjZHMpLCBdKQojICAgcm9vdF9wcl9ub2RlcyA8LQojICAgaWdyYXBoOjpWKHByaW5jaXBhbF9ncmFwaChjZHMpW1siVU1BUCJdXSkkbmFtZVthcy5udW1lcmljKG5hbWVzCiMgICAod2hpY2gubWF4KHRhYmxlKGNsb3Nlc3RfdmVydGV4W2NlbGxfaWRzLF0pKSkpXQojICAgCiMgICByb290X3ByX25vZGVzCiMgfQoKIyMgY2FsY3VsYXRlIHBzZXVkb3RpbWUKI21vbm9jbGUub2JqZWN0LmFsbCA9IG9yZGVyX2NlbGxzKG1vbm9jbGUub2JqZWN0LmFsbCwgcm9vdF9wcl9ub2Rlcz1nZXRfZWFybGllc3RfcHJpbmNpcGFsX25vZGUobW9ub2NsZS5vYmplY3QuYWxsKSkKbW9ub2NsZS5vYmplY3QuYWxsID0gb3JkZXJfY2VsbHMobW9ub2NsZS5vYmplY3QuYWxsKQojIyB1c2VkIDUgcG9pbnRzIGF0IHRoZSBiZWdpbm5pbmcKCgojIyBwbG90CnVtYXBfcHQgPC0gcGxvdF9jZWxscyhtb25vY2xlLm9iamVjdC5hbGwsIGNvbG9yX2NlbGxzX2J5ID0gInBzZXVkb3RpbWUiLCBsYWJlbF9jZWxsX2dyb3Vwcz1GQUxTRSwgY2VsbF9zaXplID0gMSwgeCA9IDEsIHkgPSAyLCBsYWJlbF9icmFuY2hfcG9pbnRzPUZBTFNFLCBsYWJlbF9sZWF2ZXM9RkFMU0UsIGxhYmVsX2dyb3Vwc19ieV9jbHVzdGVyPUZBTFNFLCBsYWJlbF9yb290cyA9IEZBTFNFKSArCiAgY29vcmRfZml4ZWQoKSArCiAgdGhlbWVfdm9pZCgpICsKICBsYWJzKHRpdGxlID0gIiIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplPTIwKSwgbGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0IChzaXplPTIwKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MjApKSArIAogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAxMCwgYmFyaGVpZ2h0ID0gMiwgdGl0bGUgPSAiUHNldWRvdGltZSIpKQoKIyMgdmlldyBwbG90CnVtYXBfcHQKCiMjIGhlbHAgd2FzIG9idGFpbmVkIGZyb20gaGVyZQojIyBodHRwczovL2dpdGh1Yi5jb20vc2F0aWphbGFiL3NldXJhdC9pc3N1ZXMvMTY1OApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9VTUFQX3B0X3d0LnBuZyIsIHBsb3QgPSB1bWFwX3B0LCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjAsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMjIyBnZ2FuaW1uYXRlIEdJRiBvZiBwc2V1b2R0aW1lCgpTZWxlY3QgYXBwcm9wcmlhdGUgY2VsbHMKYGBge3J9CnBsb3QgPC0gRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBsYWJlbCA9IEZBTFNFLCByZXBlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjEsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikKSG92ZXJMb2NhdG9yKHBsb3QsIGluZm9ybWF0aW9uID0gRmV0Y2hEYXRhKG9iamVjdCA9IHRlbnguanVzdHd0LmludGVncmF0ZWQsIHZhcnMgPSAnbW9ub2NsZV9zZXgnKSkKYGBgCgpgYGB7cn0KY2VsbHNfdG9fcmVtb3ZlIDwtIGMoIlNDMjY3NzlfOF8yODAiLCAiQ1RHR1RDVEFHQ0FHQVRDRyIpCmBgYAoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKQpsaWJyYXJ5KGdnYW5pbWF0ZSkKI2luc3RhbGwucGFja2FnZXMoImdpZnNraSIpCiNpbnN0YWxsLnBhY2thZ2VzKCJhdiIpCiNsaWJyYXJ5KGdpZnNraSkKI2xpYnJhcnkoYXYpCgojIyBtYWtlIGRhdGFmcmFtZSBmb3IgcGxvdHRpbmcKIyMgZXh0cmFjdCBkYXRhIGZvciBHR3Bsb3QgdmVyc2lvbiBvZiB0aGlzCmRmX2FuaW1hdGlvbiA8LSBhcy5kYXRhLmZyYW1lKG1vbm9jbGUub2JqZWN0LmFsbEBpbnRfY29sRGF0YUBsaXN0RGF0YSRyZWR1Y2VkRGltc0BsaXN0RGF0YVtbIlVNQVAiXV0pCiMjIGFkZCBwdCB0byB0aGlzIGRhdGEgZnJhbWU6CnB0X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHBzZXVkb3RpbWUobW9ub2NsZS5vYmplY3QuYWxsLCByZWR1Y3Rpb25fbWV0aG9kID0gIlVNQVAiKSkKZGZfYW5pbWF0aW9uIDwtIG1lcmdlKGRmX2FuaW1hdGlvbiwgcHRfdmFsdWVzLCBieT0icm93Lm5hbWVzIikgCnJvd25hbWVzKGRmX2FuaW1hdGlvbikgPC0gZGZfYW5pbWF0aW9uJFJvdy5uYW1lcwpjb2xuYW1lcyhkZl9hbmltYXRpb24pWzRdIDwtICJwdCIKCiMjIG1ha2UgdGhlIHN0YXRpYyBwbG90CnAgPC0gZ2dwbG90KGRmX2FuaW1hdGlvbiwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIsIGNvbG91ciA9IHB0KSkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfY29sb3VyX3ZpcmlkaXNfYyhvcHRpb24gPSAicGxhc21hIikgKwogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQojIyB2aWV3IHBsb3QKcGxvdChwKQoKIyMgbWFrZSBhbmltYXRlZCBwbG90CiMjIG1ha2UgYSBjYXRlZ29yeSBmb3IgYW5pbWF0aW9uCiNkZl9hbmltYXRpb24kZ3JvdXAgPC0gY3V0KGRmX2FuaW1hdGlvbiRwdCwgMTUpCgphbmltIDwtIHAgKwogIHRyYW5zaXRpb25fdGltZShwdCkgKwogIHNoYWRvd19tYXJrKCkKCmFuaW1hdGUoYW5pbSwgaGVpZ2h0ID0gMywgd2lkdGggPSAzLCB1bml0cyA9ICJpbiIsIHJlcyA9IDE1MCwgYmcgPSAndHJhbnNwYXJlbnQnKQoKIyMgdG8gY2hhbmdlIHRoZSByZXNvbHV0aW9uIC0gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDkwNTg1NjcvZGVmaW5lLXNpemUtZm9yLWdpZi1jcmVhdGVkLWJ5LWdnYW5pbWF0ZS1jaGFuZ2UtZGltZW5zaW9uLXJlc29sdXRpb24gCmBgYApTYXZlIGFuaW1hdGlvbgpgYGB7cn0KYW5pbV9zYXZlKCJhbmltYXRlZF9VTUFQX3RyYW5zcGFyZW50X2JnX3d0LmdpZiIsIHBhdGggPSAiLi4vaW1hZ2VzX3RvX2V4cG9ydC8iKQpgYGAKCmBgYHtyfQojIyBleHRyYWN0IHB0IHZhbHVlcwpwdF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZShwc2V1ZG90aW1lKG1vbm9jbGUub2JqZWN0LmFsbCwgcmVkdWN0aW9uX21ldGhvZCA9ICJVTUFQIikpCgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEFkZE1ldGFEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHB0X3ZhbHVlcywgIm9sZF9wdF92YWx1ZXMiKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdnYW5pbWF0ZSkKCiMjIG1ha2UgZGF0YWZyYW1lIGZvciBwbG90dGluZwojIyBleHRyYWN0IGRhdGEgZm9yIEdHcGxvdCB2ZXJzaW9uIG9mIHRoaXMKZGZfYW5pbWF0aW9uIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MpCiMjIGFkZCBwdCB0byB0aGlzIGRhdGEgZnJhbWU6CnB0X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhWyAsYygib2xkX3B0X3ZhbHVlcyIsICJwdF9pZF9jb2xzIiksIGRyb3AgPSBGQUxTRV0pCmRmX2FuaW1hdGlvbiA8LSBtZXJnZShkZl9hbmltYXRpb24sIHB0X3ZhbHVlcywgYnk9InJvdy5uYW1lcyIpIApyb3duYW1lcyhkZl9hbmltYXRpb24pIDwtIGRmX2FuaW1hdGlvbiRSb3cubmFtZXMKY29sbmFtZXMoZGZfYW5pbWF0aW9uKVs0XSA8LSAicHQiCiMjIHJlbW92ZSBvdXRsaWVyIGNlbGxzCmRmX2FuaW1hdGlvbiA8LSBkZl9hbmltYXRpb25bd2hpY2goZGZfYW5pbWF0aW9uJFJvdy5uYW1lcyAlbmklIGNlbGxzX3RvX3JlbW92ZSksIF0KCiNkZl9hbmltYXRpb24gPC0gZGZfYW5pbWF0aW9uW29yZGVyKGRmX2FuaW1hdGlvbiRwdCwgZGVjcmVhc2luZyA9IFRSVUUpLCBdCgojIyBtYWtlIGEgY2F0ZWdvcnkgZm9yIGFuaW1hdGlvbgojZGZfYW5pbWF0aW9uJGdyb3VwIDwtIGFzLm51bWVyaWMoY3V0KGRmX2FuaW1hdGlvbiRwdCwgMTAsIGluY2x1ZGUubG93ZXN0ID0gVFJVRSwgbGFiZWxzID0gYygxOjEwKSkpCgojIyBtYWtlIHRoZSBzdGF0aWMgcGxvdApwIDwtIGdncGxvdChkZl9hbmltYXRpb24sIGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yKSkgKwogIGdlb21fcG9pbnQoY29sID0gZGZfYW5pbWF0aW9uJHB0X2lkX2NvbHMpICsKICAjc2NhbGVfY29sb3VyX3ZpcmlkaXNfYyhvcHRpb24gPSAicGxhc21hIikgKwogIGNvb3JkX2ZpeGVkKCkgKwogIHRoZW1lX3ZvaWQoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgdmlld19zdGF0aWMoKQojIyB2aWV3IHBsb3QKcGxvdChwKQoKIyMgbWFrZSBhbmltYXRlZCBwbG90CgoKYW5pbSA8LSBwICsKICB0cmFuc2l0aW9uX3RpbWUocHQpICsKICBzaGFkb3dfbWFyaygpICsKICAjc2hhZG93X3dha2Uod2FrZV9sZW5ndGggPSAwLjk5KSAjKwogIGVudGVyX2ZhZGUoKQoKYW5pbWF0ZShhbmltLCAKICAgICAgICBoZWlnaHQgPSAzLCAKICAgICAgICB3aWR0aCA9IDMsIAogICAgICAgIHVuaXRzID0gImluIiwgCiAgICAgICAgcmVzID0gMzAwLCAKICAgICAgICBiZyA9ICd3aGl0ZScsIAogICAgICAgICNkdXJhdGlvbiA9IDYsIAogICAgICAgIGZwcyA9IDIwLCAKICAgICAgICBkZXZpY2UgPSAicG5nIiwKICAgICAgICAjcmVmX2ZyYW1lID0gMQogICAgICAgIGVuZF9wYXVzZSA9IDEwCiAgICAgICAgKQoKIyMgc2F2ZQphbmltX3NhdmUoImFuaW1hdGVkX1VNQVBfaGlnaHJlcy5naWYiLCBwYXRoID0gIi4uL2ltYWdlc190b19leHBvcnQvIikKCiMjIHRvIGNoYW5nZSB0aGUgcmVzb2x1dGlvbiAtIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQ5MDU4NTY3L2RlZmluZS1zaXplLWZvci1naWYtY3JlYXRlZC1ieS1nZ2FuaW1hdGUtY2hhbmdlLWRpbWVuc2lvbi1yZXNvbHV0aW9uIApgYGAKCgojIyMjIERlZmluZSBjZWxsIGlkZW50aXRpZXMgd2l0aCBicmFuY2hlcwoKRGVmaW5lIGlkZW50aXRpZXMgb2YgY2VsbHMgCgptYWxlCmBgYHtyfQptb25vY2xlLm9iamVjdF9tYWxlIDwtIGNob29zZV9ncmFwaF9zZWdtZW50cyhtb25vY2xlLm9iamVjdC5hbGwpCmBgYApmZW1hbGUKYGBge3J9Cm1vbm9jbGUub2JqZWN0X2ZlbWFsZSA8LSBjaG9vc2VfZ3JhcGhfc2VnbWVudHMobW9ub2NsZS5vYmplY3QuYWxsKQpgYGAKYmlwb3RlbnRpYWwKYGBge3J9Cm1vbm9jbGUub2JqZWN0X2JpcG90IDwtIGNob29zZV9ncmFwaF9zZWdtZW50cyhtb25vY2xlLm9iamVjdC5hbGwpCmBgYAphc2V4dWFsIChwcmUtYnJhbmNoKQpgYGB7cn0KbW9ub2NsZS5vYmplY3RfYXNleF9wcmUgPC0gY2hvb3NlX2dyYXBoX3NlZ21lbnRzKG1vbm9jbGUub2JqZWN0LmFsbCkKYGBgCmFzZXh1YWwgZmF0ZQpgYGB7cn0KbW9ub2NsZS5vYmplY3RfYXNleF9mYXRlIDwtIGNob29zZV9ncmFwaF9zZWdtZW50cyhtb25vY2xlLm9iamVjdC5hbGwpCmBgYApjaGVjawpgYGB7cn0KZGZfZnJlcSA8LSBkYXRhLmZyYW1lKHRhYmxlKGMoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfbWFsZSksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2ZlbWFsZSksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2JpcG90KSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9wcmUpLCBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X2ZhdGUpKSkpCnBhc3RlKCJudW1iZXIgb2YgY2VsbHMgaW4gc2V1cmF0IG9iamVjdCBpcyIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdC5hbGwpKSwgIi4gVGhlIG51bWJlciBvZiBjZWxscyBzZWxlY3RlZCBoZXJlIHdpdGggYW4gaWRlbnRpdGl0eSBpcyIsIGRpbShkZl9mcmVxKVsxXSkKZGZfZnJlcSA8LSBkZl9mcmVxW2RmX2ZyZXEkRnJlcSA+IDEsIF0KZGZfZnJlcQpgYGAKSW5zcGVjdCB3aGVyZSB0aGVzZSBtaXNzaW5nIGNlbGxzIGFyZToKYGBge3J9CiMgJyVuaSUnIDwtIE5lZ2F0ZSgnJWluJScpCiMgCiMgbm90X2Fzc2lnbmVkX2NlbGxzIDwtIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0LmFsbClbY29sbmFtZXMobW9ub2NsZS5vYmplY3QuYWxsKSAlbmklIGMoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfbWFsZSksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2ZlbWFsZSksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2JpcG90KSwgY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleCksIGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfZmF0ZSkpXQojIAojIERpbVBsb3Qoc2V1cmF0Lm9iamVjdCwgcmVwZWwgPSBUUlVFLCBsYWJlbC5zaXplID0gNSwgcHQuc2l6ZSA9IDAuNSwgY2VsbHMuaGlnaGxpZ2h0ID0gbm90X2Fzc2lnbmVkX2NlbGxzLCBkaW1zID0gYygyLDEpLCByZWR1Y3Rpb24gPSAiRElNX1VNQVAiKSArCiMgICBjb29yZF9maXhlZCgpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiMwMDAwMDAiLCAiI2Y1NGUxZSIpKQpgYGAKCmBgYHtyfQojIyBjcmVhdGUgYW5ub3RhdGlvbiBkYXRhZnJhbWUgZnJvbSB0aGVzZSByZXN1bHRzOgpkZl9tb25vY2xlX3NleGVzIDwtIHJiaW5kKGRhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9tYWxlKSwgInNleCIgPSByZXAoIk1hbGUiLCBsZW5ndGgoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfbWFsZSkpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5mcmFtZSgiY2VsbF9uYW1lIiA9IGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2ZlbWFsZSksICJzZXgiID0gcmVwKCJGZW1hbGUiLCBsZW5ndGgoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfZmVtYWxlKSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKCJjZWxsX25hbWUiID0gY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYmlwb3QpLCAic2V4IiA9IHJlcCgiQmlwb3RlbnRpYWwiLCBsZW5ndGgoY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYmlwb3QpKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X3ByZSksICJzZXgiID0gcmVwKCJBc2V4dWFsX0Vhcmx5IiwgbGVuZ3RoKGNvbG5hbWVzKG1vbm9jbGUub2JqZWN0X2FzZXhfcHJlKSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKCJjZWxsX25hbWUiID0gY29sbmFtZXMobW9ub2NsZS5vYmplY3RfYXNleF9mYXRlKSwgInNleCIgPSByZXAoIkFzZXh1YWxfTGF0ZSIsIGxlbmd0aChjb2xuYW1lcyhtb25vY2xlLm9iamVjdF9hc2V4X2ZhdGUpKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgI2RhdGEuZnJhbWUoImNlbGxfbmFtZSIgPSBub3RfYXNzaWduZWRfY2VsbHMsICJzZXgiID0gcmVwKCJVbmFzc2lnbmVkIiwgbGVuZ3RoKG5vdF9hc3NpZ25lZF9jZWxscykpKQogICAgICAgICAgICAgICAgICAgICAgICAgICkKCmRpbShkZl9tb25vY2xlX3NleGVzKQoKIyMgb3JkZXIgbGlrZSB0aGUgbWV0YWRhdGEKZGZfbW9ub2NsZV9zZXhlcyA8LSBkZl9tb25vY2xlX3NleGVzW21hdGNoKHJvd25hbWVzKG1vbm9jbGUub2JqZWN0LmFsbEBjb2xEYXRhKSwgZGZfbW9ub2NsZV9zZXhlcyRjZWxsX25hbWUpLCBdCgojIyBhZGQgdGhpcyBiYWNrIGludG8gdGhlIG1vbm9jbGUgb2JqZWN0Cm1vbm9jbGUub2JqZWN0LmFsbEBjb2xEYXRhJFNleGVzX21vbm9jbGUgPC0gZGZfbW9ub2NsZV9zZXhlcyRzZXgKCiMjIGFkZCB0aGlzIHRvIHRoZSBzZXVyYXQgb2JqZWN0CnJvd25hbWVzKGRmX21vbm9jbGVfc2V4ZXMpIDwtIGRmX21vbm9jbGVfc2V4ZXMkY2VsbF9uYW1lCmRmX21vbm9jbGVfc2V4ZXNfdG9fYWRkX3RvX3NldXJhdCA8LSBkZl9tb25vY2xlX3NleGVzWyxjKCJzZXgiKSwgZHJvcCA9IEZBTFNFXQp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkIDwtIEFkZE1ldGFEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRmX21vbm9jbGVfc2V4ZXNfdG9fYWRkX3RvX3NldXJhdCwgY29sLm5hbWUgPSAibW9ub2NsZV9zZXgiKQpgYGAKCnB0IHZzLiByZWFsIHRpbWUKYGBge3J9CmxpYnJhcnkoZ2dyaWRnZXMpCgpkZl9wbG90dGluZyA8LSBhcy5kYXRhLmZyYW1lKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhKQoKcHRfcmVhbF9wbG90IDwtIGdncGxvdChkZl9wbG90dGluZywgYWVzKHggPSBvbGRfcHRfdmFsdWVzLCB5ID0gIGFzLmZhY3RvcihQcmVkaWN0aW9uLlNwZWFybWFuLiksIGZpbGwgPSBhcy5mYWN0b3IoUHJlZGljdGlvbi5TcGVhcm1hbi4pKSkgKwogIGdlb21fZGVuc2l0eV9yaWRnZXMoYWxwaGEgPSAuMSwKICAgICAgICAgICAgICAgICAgICAgIHJlbF9taW5faGVpZ2h0ID0gMC4wMywgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVhbnRpbGVfbGluZXMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1YW50aWxlcyA9IDIsCiAgICAgICAgICAgICAgICAgICAgICBzY2FsZSA9IDIpICsgIyBwbG90IHJpZ2RlbGluZXMgd2l0aG91dCBwb2ludHMKICAjIHBsb3QgcG9pbnRzIHdpdGggaW52aXNpYmxlIHJpZGdlbGluZXMKICBnZW9tX2RlbnNpdHlfcmlkZ2VzX2dyYWRpZW50KHBvaW50X2FscGhhID0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyZWRfcG9pbnRzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyhwb2ludF9jb2xvciA9IG1vbm9jbGVfc2V4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShkcm9wPUZBTFNFKSArCiAgbGFicyh0aXRsZSA9ICcnLCB4ID0gIlBzZXVkb3RpbWUiLCB5ID0gIlByZWRpY3RlZCBSZWFsLXRpbWUgKGhwaSkiKSArCiAgI3NjYWxlX2ZpbGxfdmlyaWRpc19jKG5hbWUgPSAicHNldWRvdGltZSIsIG9wdGlvbiA9ICJDIiwgYWxwaGEgPSAxKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKHNpemUgPSAoMC4yKSwgY29sb3VyPSJncmV5IikKICAgICAgICApCgpwdF9yZWFsX3Bsb3QKYGBgCgpgYGB7cn0KZ2cgPC0gZ2dwbG90KGRmX3Bsb3R0aW5nLCBhZXMoYXMuZmFjdG9yKFByZWRpY3Rpb24uU3BlYXJtYW4uKSwgZmlsbCA9IG1vbm9jbGVfc2V4KSkgKyBnZW9tX2JhcihzdGF0ID0gImNvdW50IiwgcG9zaXRpb249ImZpbGwiKQoKZ2cKYGBgCgoKIyA4LiBQbG90cyB7LnRhYnNldH0KCm1ha2UgY29tcG9zaXRlIHBzZXVkb3RpbWUvSUQgZmlndXJlCgpgYGB7cn0KIyAxID0gYmx1ZSAtICIjMDA1MmM1IgojIDIgPSByZWQgLSAiI2E1MmIxZSIKIyAzID0gZ3JlZW4gLSAiIzAxNmMwMCIKIyA0ID0geWVsbG93IC0gIiNmZmU0MDAiCiNwYWxfc2V4IDwtIGMoIiMwMDUyYzUiLCIjZmZlNDAwIiwgIiNhNTJiMWUiLCAiIzAxNmMwMCIpCgojIyBleHRyYWN0IHBzZXVkb3RpbWUgbnVtYmVycyBhbmQgaWRlbnRpdHkgb2YgY2VsbHMgdG8gYSBkYXRhZnJhbWUKZGZfcHRfaWQgPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbLGMoIm9sZF9wdF92YWx1ZXMiLCAibW9ub2NsZV9zZXgiKV0KCiMjIGluc3BlY3QgcG9zc2libGUgdmFsdWVzCmxpc3Rfb2Zfc2V4ZXMgPC0gbmFtZXModGFibGUoZGZfcHRfaWQkbW9ub2NsZV9zZXgpKQoKIyMgbWFrZSBhIG5ldyBjb2x1bW4KZGZfcHRfaWQkY29sb3VyIDwtIE5BCgojIyBtYWtlIGNvbG91ciByYW1wcwphc2V4X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRDVFM0Y1IiwgIiMwMDUyYzUiKSkKbWFsZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygid2hpdGUiLCAieWVsbG93IiwgIiMwMTZjMDAiKSkKZmVtYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ5ZWxsb3ciLCAiI2E1MmIxZSIpKQpiaXBvdF9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygid2hpdGUiLCAiI2ZmZTQwMCIpKQoKIyMgcmUtY2xhc3NpZnkgdGhlIGNlbGxzIHRoYXQgYXJlIHVuYXNzaWduZWQgY2VsbHMgcmVtb3ZlZCBmcm9tIHNleHVhbCBicmFuY2ggYWJvdmU6CiNkZl9wdF9pZFt3aGljaChyb3duYW1lcyhkZl9wdF9pZCkgJWluJSByZW1vdmVfY2VsbHMpLCBdJG1vbm9jbGVfc2V4IDwtICJBc2V4dWFsIgoKIyMgYXNzaWduIHZhbHVlcyB0byBlYWNoIGNsdXN0ZXIKIyMgaGVscCBoZXJlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy85OTQ2NjMwL2NvbG91ci1wb2ludHMtaW4tYS1wbG90LWRpZmZlcmVudGx5LWRlcGVuZGluZy1vbi1hLXZlY3Rvci1vZi12YWx1ZXMgCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJGNvbG91ciA8LSBhc2V4X3JhbXAoMTAwKVthcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9FYXJseSIgfCBkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9MYXRlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpXQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJGNvbG91ciA8LSBtYWxlX3JhbXAoMTAwKVthcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKV0KCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJGNvbG91ciA8LSBmZW1hbGVfcmFtcCgxMDApW2FzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSldCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJGNvbG91ciA8LSBiaXBvdF9yYW1wKDEwMClbYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkJpcG90ZW50aWFsIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpXQoKIyMgY2hlY2sgZXZlcnl0aGluZyBoYXMgYSB2YWx1ZQojdGFibGUoaXMubmEoZGZfcHRfaWQkY29sb3VyKSkKCiMjIG1ha2UgaW50byBhIGRmCiNkZl9wdF9pZCA8LSBkZl9wdF9pZFsgLCJjb2xvdXIiLCBkcm9wID0gRkFMU0VdCgojIyBhZGQgYmFjayB0byBzZXVyYXQgb2JqZWN0CmRmIDwtIGRmX3B0X2lkWyAsImNvbG91ciIsIGRyb3AgPSBGQUxTRV0KdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSBBZGRNZXRhRGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkZiwgInB0X2lkX2NvbHMiKQpybShkZikKCiMjIHBsb3QKIyMgZXh0cmFjdCBVTUFQIGNvb3JkcwpkZl91bWFwX3Bsb3QgPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MKZGZfdW1hcF9wbG90IDwtIG1lcmdlKGRmX3VtYXBfcGxvdCwgZGZfcHRfaWQsIGJ5PTAsIGFsbD1UUlVFKQoKIyMgYWRkIHRyZWUKIyNUaGUgdHJlZSBmb3IgbW9ub2NsZSBpcyBsb2NhdGVkIGhlcmU6CiMgbW9ub2NsZS5vYmplY3RAcHJpbmNpcGFsX2dyYXBoX2F1eFtbIlVNQVAiXV0kZHBfbXN0IAppY2Ffc3BhY2VfZGYgPC0gdChtb25vY2xlLm9iamVjdC5hbGxAcHJpbmNpcGFsX2dyYXBoX2F1eFtbIlVNQVAiXV0kZHBfbXN0KSAlPiUKICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JQogICAgICBkcGx5cjo6c2VsZWN0XyhwcmluX2dyYXBoX2RpbV8xID0gIlVNQVBfMSIsIHByaW5fZ3JhcGhfZGltXzIgPSAiVU1BUF8yIikgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoc2FtcGxlX25hbWUgPSByb3duYW1lcyguKSwKICAgICAgICAgICAgICAgICAgICBzYW1wbGVfc3RhdGUgPSByb3duYW1lcyguKSkKCmRwX21zdCA8LSBtb25vY2xlLm9iamVjdC5hbGxAcHJpbmNpcGFsX2dyYXBoW1siVU1BUCJdXQoKZWRnZV9kZiA8LSBkcF9tc3QgJT4lCiAgICAgIGlncmFwaDo6YXNfZGF0YV9mcmFtZSgpICU+JQogICAgICBkcGx5cjo6c2VsZWN0Xyhzb3VyY2UgPSAiZnJvbSIsIHRhcmdldCA9ICJ0byIpICU+JQogICAgICBkcGx5cjo6bGVmdF9qb2luKGljYV9zcGFjZV9kZiAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3RfKAogICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U9InNhbXBsZV9uYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlX3ByaW5fZ3JhcGhfZGltXzE9InByaW5fZ3JhcGhfZGltXzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VfcHJpbl9ncmFwaF9kaW1fMj0icHJpbl9ncmFwaF9kaW1fMiIpLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInNvdXJjZSIpICU+JQogICAgICBkcGx5cjo6bGVmdF9qb2luKGljYV9zcGFjZV9kZiAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3RfKAogICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ9InNhbXBsZV9uYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0X3ByaW5fZ3JhcGhfZGltXzE9InByaW5fZ3JhcGhfZGltXzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRfcHJpbl9ncmFwaF9kaW1fMj0icHJpbl9ncmFwaF9kaW1fMiIpLAogICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInRhcmdldCIpCgojIyBtYWtlIGdncGxvdAp1bWFwX2lkX3B0IDwtIGdncGxvdChkZl91bWFwX3Bsb3QsIGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yKSkgKyAKICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wb2ludChjb2wgPSBkZl91bWFwX3Bsb3QkY29sb3VyKSArCiAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKwogICAgICAgICAgICAgICAgICAgICBnZW9tX3NlZ21lbnQoYWVzX3N0cmluZyh4PSJzb3VyY2VfcHJpbl9ncmFwaF9kaW1fMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PSJzb3VyY2VfcHJpbl9ncmFwaF9kaW1fMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ZW5kPSJ0YXJnZXRfcHJpbl9ncmFwaF9kaW1fMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ZW5kPSJ0YXJnZXRfcHJpbl9ncmFwaF9kaW1fMiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZWRnZV9kZikKCnVtYXBfaWRfcHQKYGBgCgpzYXZlCmBgYHtyfQojZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L3VtYXBfaWRfcHQucG5nIiwgcGxvdCA9IHVtYXBfaWRfcHQsIGRldmljZSA9ICJwbmciLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDIxLCBoZWlnaHQgPSAyOS43LCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCmNsdXN0ZXIgcGxvdApgYGB7cn0KIyMjIFByZXBhcmUgZGF0YQoKIyMgZXh0cmFjdCBkZiB3aXRoIGNsdXN0ZXIgSUQsIApkZl9wdF9pZCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVsgLCJzZXVyYXRfY2x1c3RlcnMiLCBkcm9wPUZBTFNFXQojIyBleHRyYWN0IFVNQVAgY29vcmRzCmRmX3Bsb3QgPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MKZGZfcGxvdCA8LSBtZXJnZShkZl9wbG90LCBkZl9wdF9pZCwgYnk9MCwgYWxsPVRSVUUpCiMjIGFkZCBjb2xvdXIgY29sCmRmX3Bsb3QkY29sb3VyIDwtIGRmX3Bsb3Qkc2V1cmF0X2NsdXN0ZXJzCmxldmVscyhkZl9wbG90JGNvbG91cikgPC0gbGlzdChwcmludChhc2V4X3JhbXAoMTcpWzFdKSA9ICI5IiwgYXNleF9yYW1wKDE3KVsyXT0iNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVszXT0iMTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzRdID0gIjgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzVdPSAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVs2XT0gICIxNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbN10gPSAiMiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbOF0gPSAiMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbOV0gPSAiMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxMF0gPSAiMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxMV0gPSAiNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxMl0gPSAiNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxM10gPSAiNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxNF0gPSAiMTIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzZXhfcmFtcCgxNylbMTVdID0gIjE4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc2V4X3JhbXAoMTcpWzE2XSA9ICIyMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNleF9yYW1wKDE3KVsxN10gPSAiMjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpcG90X3JhbXAoMylbMl0gPSAiMTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbGVfcmFtcCgzKVsyXSA9ICIxNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFsZV9yYW1wKDMpWzNdID0gIjEzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZW1hbGVfcmFtcCg0KVsyXSA9ICIyMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlX3JhbXAoNClbM10gPSAiMjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZV9yYW1wKDQpWzRdID0gIjE5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZW1hbGVfcmFtcCg0KVs0XSA9ICIxNyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMjIGFhYmJyZXZpYXRlIGNsdXN0ZXJzCmRmX3Bsb3QkY2x1c3Rlcl9uYW1lcyA8LSBkZl9wbG90JHNldXJhdF9jbHVzdGVycwpsZXZlbHMoZGZfcGxvdCRjbHVzdGVyX25hbWVzKSA8LSBsaXN0KEFfMT0iOSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMj0iNCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMz0iMTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzQgPSAiOCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfNSA9ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzY9ICAiMTQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzcgPSAiMiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfOCA9ICIxMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV85ID0gIjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTAgPSAiMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMSA9ICI2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzEyID0gIjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTMgPSAiNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNCA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNSA9ICIxOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNiA9ICIyMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xNyA9ICIyMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQiA9ICIxMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTV8xID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNXzIgPSAiMTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMSA9ICIyMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8yID0gIjIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzMgPSAiMTkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMyA9ICIxNyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpsaWJyYXJ5KGRwbHlyKQpkYXQlPiUKZ3JvdXBfYnkoY3VzdGlkKSU+JSAKc3VtbWFyaXNlKE1lYW49bWVhbih2YWx1ZSksIE1heD1tYXgodmFsdWUpLCBNaW49bWluKHZhbHVlKSwgTWVkaWFuPW1lZGlhbih2YWx1ZSksIFN0ZD1zZCh2YWx1ZSkpCgoKCiMjIHBsb3QKdW1hcF9pZCA8LSBnZ3Bsb3QoZGZfcGxvdCwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIpKSArIAogICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KGNvbCA9IGRmX3Bsb3QkY29sb3VyKSArCiAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArCiAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkKCnVtYXBfaWQKYGBgCgpgYGB7cn0KIyMgdGhlc2UgZ2V0IGRlZmluZWQgbGF0ZXIgb24sIGJ1dCBhcmUgcmVwbGljYXRlZCBhYm92ZSBoZXJlIGZvciBwbG90dGluZwphc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzIDwtIGMoOSwgNCwgMTUsIDgsIDEsIDE0LCAyLCAxMCwgMywgMCwgNiwgNSkKYXNleHVhbF9sYXRlX2NsdXN0ZXJzIDwtIGMoNywgMTIsIDE4LCAyMCwgMjMpCmJpcG90ZW50aW9uYWxfZWFybHlfY2x1c3RlcnMgPC0gIyAwPwpiaXBvdGVudGlhbF9jbHVzdGVycyA8LSBjKDExKSAKbWFsZV9jbHVzdGVycyA8LSBjKDE2LCAxMykKZmVtYWxlX2NsdXN0ZXJzIDwtIGMoMjEsIDIyLCAxNywgMTkpCgojIyBtYWtlIGEgbmV3IGNvbHVtbiBmb3IgcGxvdHRpbmcKdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnMKCiMjIHJlb3JkZXIgdGhlIGxldmVscyBzbyB5b3UgY2FuIHBsb3QgdGhlIGNsdXRlcnMgYXMgeW91IHdpc2gKbXlfbGV2ZWxzIDwtIGMoYXNleHVhbF9lYXJseV9jbHVzdGVycyxhc2V4dWFsX2xhdGVfY2x1c3RlcnMsIGJpcG90ZW50aWFsX2NsdXN0ZXJzLCBtYWxlX2NsdXN0ZXJzLCBmZW1hbGVfY2x1c3RlcnMpCnRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcgPC0gZmFjdG9yKHggPSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nLCBsZXZlbHMgPSBteV9sZXZlbHMpCgojIyBjaGFuZ2UgdGhlIGxldmVscwpsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZykgPC0gbGlzdChBXzE9IjkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzI9IjQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzM9IjE1IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV80ID0gIjgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzUgPSAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV82PSAgIjE0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV83ID0gIjIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzggPSAiMTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfOSA9ICIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzEwID0gIjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTEgPSAiNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQV8xMiA9ICI1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBXzEzID0gIjciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTQgPSAiMTIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTUgPSAiMTgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTYgPSAiMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFfMTcgPSAiMjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFAgPSAiMTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1fMSA9ICIxNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTV8yID0gIjEzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzEgPSAiMjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZfMiA9ICIyMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRl8zID0gIjE5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGXzMgPSAiMTciCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKIyMjIEFubm90YXRpb24gc2V0LXVwCgojIyBleHRyYWN0IHBzZXVkb3RpbWUgbnVtYmVycyBhbmQgaWRlbnRpdHkgb2YgY2VsbHMgdG8gYSBkYXRhZnJhbWUKZGZfcHRfaWQgPC0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbLGMoIm9sZF9wdF92YWx1ZXMiLCAibW9ub2NsZV9zZXgiLCAic2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyIsICJQcmVkaWN0aW9uLlNwZWFybWFuLiIsICJQcmVkaWN0aW9uLlNwZWFybWFuLl9LYXNpYSIpXQoKIyMgbWFrZSBhIG5ldyBjb2x1bW4KZGZfcHRfaWQkY29sb3VyIDwtIE5BCgojIyBhc3NpZ24gYmlucyB0byBlYWNoIG9mIHRoZSB2YWx1ZXMKIyMgaGVscCBoZXJlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy85OTQ2NjMwL2NvbG91ci1wb2ludHMtaW4tYS1wbG90LWRpZmZlcmVudGx5LWRlcGVuZGluZy1vbi1hLXZlY3Rvci1vZi12YWx1ZXMgCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9FYXJseSIgfCBkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQXNleHVhbF9MYXRlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiTWFsZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiRmVtYWxlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkZlbWFsZSIsIF0kb2xkX3B0X3ZhbHVlcyxicmVha3MgPSAxMDApKQoKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkJpcG90ZW50aWFsIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkJpcG90ZW50aWFsIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgojIyBtYWtlIGNvbG91ciByYW1wcwphc2V4X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRDVFM0Y1IiwgIiMwMDUyYzUiKSkKbWFsZV9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygid2hpdGUiLCAieWVsbG93IiwgIiMwMTZjMDAiKSkKZmVtYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ5ZWxsb3ciLCAiI2E1MmIxZSIpKQpiaXBvdF9yYW1wIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygid2hpdGUiLCAiI2ZmZTQwMCIpKQoKIyMgYXNzaWduIHZhbHVlcyB0byBlYWNoIGNsdXN0ZXIKIyMgdGFrZSB0aGUgbWVhbiBvZiB0aGUgYmluCmRmX2Fubm90YXRpb24gPC0gYWdncmVnYXRlKGRmX3B0X2lkWywgImNvbG91ciJdLCBsaXN0KGRmX3B0X2lkJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpLCBtZWFuKQojIyBCRUNBVVNFIHdlIGhhdmUgb3JkZXJlZCB0aGUgY2x1c3RlcnMgYWxyZWFkeSwgd2UgY2FuIHNpbXBseSB0YWtlIHRoZSByb3cgaW5kZXggZm9yIHRoaXMgYml0CmRmX2Fubm90YXRpb24kY29sb3VyIDwtIE5BCmRmX2Fubm90YXRpb25bMToxNywgXSRjb2xvdXIgPC0gYXNleF9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOjE3LCBdJHhdCmRmX2Fubm90YXRpb25bMTgsIF0kY29sb3VyIDwtIGJpcG90X3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE4LCBdJHhdCmRmX2Fubm90YXRpb25bMTk6MjAsIF0kY29sb3VyIDwtIG1hbGVfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMTk6MjAsIF0keF0KZGZfYW5ub3RhdGlvblsyMToyMywgXSRjb2xvdXIgPC0gZmVtYWxlX3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzIxOjIzLCBdJHhdCgojIyBtYWtlIGNvbG91ciBwYWxsZXRlCiNwYWxfcGxvdCA8LSBjKGFzZXhfcmFtcCgxNzApWzEsMTEsMjEsMzEsXSwgYmlwb3RfcmFtcCgzKVsyXSwgbWFsZV9yYW1wKDUpWzM6NF0sIGZlbWFsZV9yYW1wKDUpWzI6NV0pCnBhbF9wbG90IDwtIGMoZGZfYW5ub3RhdGlvbiRjb2xvdXIsICcjNDlDMTZERkYnKQoKIyMgcGxvdAp1bWFwX3dpdGhfY2x1c3RlcnMgPC0gRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLAogICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmciLAogICAgICAgIGRpbXMgPSBjKDEsMiksIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgcHQuc2l6ZSA9IDEsCiAgICAgICAgbGFiZWwuYm94ID0gVFJVRSwKICAgICAgICBsYWJlbC5zaXplID0gOCwKICAgICAgICBsYWJlbC5jb2xvcgk9IGMocmVwKGMoIiMwMDAwMDAiKSwgMTIpLCByZXAoYygiI2ZmZmZmZiIpLCA1KSwgcmVwKGMoIiMwMDAwMDAiKSwgMiksIiNmZmZmZmYiLCAiIzAwMDAwMCIsICIjZmZmZmZmIiwgIiNmZmZmZmYiKSwKICAgICAgICBvcmRlciA9IFRSVUUsIAogICAgICAgIHJlcGVsID0gVFJVRSwgCiAgICAgICAgbGFiZWwgPSBUUlVFLAogICAgICAgIGNvbHMgPSBwYWxfcGxvdCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKCJBc2V4dWFsIDEiLCAiQXNleHVhbCAyIiAsICJBc2V4dWFsIDMiLCAiQXNleHVhbCA0IiwgIkFzZXh1YWwgNSIsICJBc2V4dWFsIDYiLCAiQXNleHVhbCA3IiwgIkFzZXh1YWwgOCIsICAiQXNleHVhbCA5IiwgIkFzZXh1YWwgMTAiLCAiQXNleHVhbCAxMSIsICJBc2V4dWFsIDEyIiwgIkFzZXh1YWwgMTMiLCAiQXNleHVhbCAxNCIsICJBc2V4dWFsIDE1IiwgIkFzZXh1YWwgMTYiLCAiQXNleHVhbCAxNyIsICJQcm9nZW5pdG9yIiwgIk1hbGUgMSIsICJNYWxlIDIiLCAiRmVtYWxlIDEiLCAiRmVtYWxlIDIiLCAiRmVtYWxlIDMiKSwgdmFsdWVzID0gcGFsX3Bsb3QpICsKICB0aGVtZV92b2lkKCkgKwogICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpCgp1bWFwX3dpdGhfY2x1c3RlcnMKYGBgCgpzYXZlCmBgYHtyfQpnZ3NhdmUoIi4uL2ltYWdlc190b19leHBvcnQvdW1hcF93aXRoX2NsdXN0ZXJzLnBuZyIsIHBsb3QgPSB1bWFwX3dpdGhfY2x1c3RlcnMsIGRldmljZSA9ICJwbmciLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDIxLCBoZWlnaHQgPSAyOS41LCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgpgYGB7cn0KIyMgZXh0cmFjdCBwcm9wb3J0aW9uIG9mIGNlbGxzCmxpYnJhcnkocGx5cikKZGZfcHJvcF9jb21iIDwtIGFzLmRhdGEuZnJhbWUodGFibGUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZywgdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkZXhwZXJpbWVudCkpCm5hbWVzKGRmX3Byb3BfY29tYikgPC0gYygiY2x1c3RlciIsICJleHBlcmltZW50IiwgIkZyZXEiKQoKIyMgY2FsY3VhbHRlIHRoZSBwZXJjZW50YWdlCmRmX3Byb3BfY29tYiRwYyA8LSBOQQpkZl9wcm9wX2NvbWJbZGZfcHJvcF9jb21iJGV4cGVyaW1lbnQgPT0gIm11dGFudHMiLCBdJHBjIDwtIChkZl9wcm9wX2NvbWJbZGZfcHJvcF9jb21iJGV4cGVyaW1lbnQgPT0gIm11dGFudHMiLCBdJEZyZXEvc3VtKGRmX3Byb3BfY29tYltkZl9wcm9wX2NvbWIkZXhwZXJpbWVudCA9PSAibXV0YW50cyIsIF0kRnJlcSkpKjEwMApkZl9wcm9wX2NvbWJbZGZfcHJvcF9jb21iJGV4cGVyaW1lbnQgPT0gInRlbnhfNWsiLCBdJHBjIDwtIChkZl9wcm9wX2NvbWJbZGZfcHJvcF9jb21iJGV4cGVyaW1lbnQgPT0gInRlbnhfNWsiLCBdJEZyZXEvc3VtKGRmX3Byb3BfY29tYltkZl9wcm9wX2NvbWIkZXhwZXJpbWVudCA9PSAidGVueF81ayIsIF0kRnJlcSkpKjEwMAoKIyMgcmVvcmRlciBsZXZlbHMgaW4gVmFyMSAKI2RmX3Byb3BfY29tYiRjbHVzdGVyIDwtIGZhY3RvcihkZl9wcm9wX2NvbWIkY2x1c3RlciwgbGV2ZWxzID0gYygidW5hc3NpZ25lZCIsICJNIiwgIkYiLCAiNSIsICI3IiwgIjQiLCAiMyIsICIxIiwgIjAiLCAiMiIsICI2IikpCgojIyB0aGVuIHJlb3JkZXIgYnkgdGhpcyBzbyB0aGUgY3Vtc3VtIHdpbGwgd29yayBiZWxvdwpkZl9wcm9wX2NvbWIgPC0gZGZfcHJvcF9jb21iW3JldihvcmRlcihkZl9wcm9wX2NvbWIkZXhwZXJpbWVudCwgZGZfcHJvcF9jb21iJGNsdXN0ZXIpKSxdCgojIyBDYWxjdWxhdGUgdGhlIGN1bXVsYXRpdmUgc3VtIG9mIGxlbiBmb3IgZWFjaCBkb3NlCmRmX2N1bXN1bSA8LSBkZHBseShkZl9wcm9wX2NvbWIsICJleHBlcmltZW50IiwgdHJhbnNmb3JtLCBsYWJlbF95cG9zPWN1bXN1bShwYykgLSAwLjUqcGMpCmhlYWQoZGZfY3Vtc3VtKQojIGh0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvd2lraS9nZ3Bsb3QyLWJhcnBsb3RzLXF1aWNrLXN0YXJ0LWd1aWRlLXItc29mdHdhcmUtYW5kLWRhdGEtdmlzdWFsaXphdGlvbgoKIyMgcmV2ZXJzZSB0aGUgbGV2ZWxzIGluIFZhcjEKI2RmX2N1bXN1bSRjbHVzdGVyIDwtIGZhY3RvcihkZl9jdW1zdW0kY2x1c3RlciwgbGV2ZWxzID0gcmV2KGMobGV2ZWxzKGRmX2N1bXN1bSRjbHVzdGVyKSkpKQojZGZfY3Vtc3VtIDwtIGRmX2N1bXN1bVtjKG1hdGNoKGRmX2N1bXN1bSRjbHVzdGVyWzE6MjNdLCBjKGxldmVscyhkZl9jdW1zdW0kY2x1c3RlcikpKSwgbWF0Y2goZGZfY3Vtc3VtJGNsdXN0ZXJbMToyM10sIGMobGV2ZWxzKGRmX2N1bXN1bSRjbHVzdGVyKSkpICsgMjMpLCBdCgpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoZ2dwdWJyKQojIyBtYWtlIHBsb3QKcGxvdF9wcm9wIDwtIGdncGxvdChkYXRhPWRmX2N1bXN1bSwgYWVzKHg9ZXhwZXJpbWVudCwgeT1wYywgZmlsbD1jbHVzdGVyKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikrCiAgZ2VvbV9sYWJlbF9yZXBlbChhZXMobGFiZWwgPSBGcmVxLCB5PWxhYmVsX3lwb3MsIGZpbGwgPSBmYWN0b3IoY2x1c3RlcikpLCBjb2xvciA9IGMocmVwKGMocmVwKGMoIiNmZmZmZmYiKSwgMiksICIjMDAwMDAwIiwgIiNmZmZmZmYiLCByZXAoYygiIzAwMDAwMCIpLCAyKSwgcmVwKGMoIiNmZmZmZmYiKSwgNSksIHJlcChjKCIjMDAwMDAwIiksIDEyKSksIDIpKSwgc2l6ZSA9IDMuNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogICNnZW9tX3RleHQoYWVzKHk9bGFiZWxfeXBvcywgbGFiZWw9RnJlcSksIHZqdXN0PTAsIGNvbG9yPSJibGFjayIsIHNpemU9My41KSArCiAgbGFicyhmaWxsID0gIkNlbGwgY2x1c3RlciIsIHk9ICJDZWxsIFByb3BvcnRpb25zICglKSIsIHggPSAiVGVjaG5vbG9neSIpICsKICBzY2FsZV9maWxsX21hbnVhbChsYWJlbHMgPSBjKCJBc2V4dWFsIDEiLCAiQXNleHVhbCAyIiAsICJBc2V4dWFsIDMiLCAiQXNleHVhbCA0IiwgIkFzZXh1YWwgNSIsICJBc2V4dWFsIDYiLCAiQXNleHVhbCA3IiwgIkFzZXh1YWwgOCIsICAiQXNleHVhbCA5IiwgIkFzZXh1YWwgMTAiLCAiQXNleHVhbCAxMSIsICJBc2V4dWFsIDEyIiwgIkFzZXh1YWwgMTMiLCAiQXNleHVhbCAxNCIsICJBc2V4dWFsIDE1IiwgIkFzZXh1YWwgMTYiLCAiQXNleHVhbCAxNyIsICJQcm9nZW5pdG9yIiwgIk1hbGUgMSIsICJNYWxlIDIiLCAiRmVtYWxlIDEiLCAiRmVtYWxlIDIiLCAiRmVtYWxlIDMiKSwgdmFsdWVzID0gcGFsX3Bsb3QpICsKICB0aGVtZV9wdWJyKCkgKwogIHRoZW1lKGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwgbGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9IHJldihjKCIxMHgiLCAiU21hcnQtc2VxMiIpKSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKG5jb2w9OSkpCgoKcGxvdF9wcm9wCmBgYApgYGB7cn0KZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L1dUX2NlbGxfdHlwZV9wcm9wb3J0aW9ucy5wbmciLCBwbG90ID0gcGxvdF9wcm9wLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAzMCwgaGVpZ2h0ID0gOSwgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKIyMjIGRvdHBsb3QKCkEgZG90cGxvdCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0aGUgZXhwcmVzc2lvbiBvZiBtdWx0aXBsZSBnZW5lcyBpbiBhIGNsZWFyZXIgd2F5IHRoYW4gc3VjY2VzaXZlIFVNQVAgcGxvdHMKCmBgYHtyLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0PSA4fQojIyMgRGF0YSBzZXQtdXAKCiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKCiMgUEJBTktBLTEzMDI3MDAgICAgICAgR0NTS08tb29tICBNRDEgCiMgUEJBTktBLTE0NDc5MDAgICAgICAgIEdDU0tPLTI5ICBNRDIKIyBQQkFOS0EtMDQxMzQwMCAgICBHQ1NLTy0xMF84MjAgIE1EMwojIFBCQU5LQS0wNzE2NTAwICAgICAgICBHQ1NLTy0xOSAgTUQ0IAojIFBCQU5LQS0wMTAyNDAwICAgICAgICAgR0NTS08tMiAgTUQ1IAoKIyBQQkFOS0EtMTQ1NDgwMCAgICAgICAgR0NTS08tMjEgIEZEMQojIFBCQU5LQS0wOTAyMzAwICAgICAgICBHQ1NLTy0xMyAgRkQyCiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKCiMgUEJBTktBLTE0Mzc1MDAgLSBBUDJHIC0gY29tbWl0bWVudAojIFBCQU5LQS0xMzE5NTAwIC0gQ0NQMiAtIGZlbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMDQxNjEwMCAtIE1HMSAtIGR5bmVuaW4gaGVhdnkgY2hhaW4gLSBtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0wODMxMDAwIC0gTVNQMSAtIGxhdGUgYXNleHVhbAojIFBCQU5LQS0xMTAyMjAwIC0gTVNQOCAtIGVhcmx5IGFzZXh1YWwgKGZyb20gQm96ZGVjaCBwYXBlcikKCm1hcmtlcl9nZW5lc19saXN0IDwtIGMoIlBCQU5LQS0xNDM3NTAwIiwgIlBCQU5LQS0xMzE5NTAwIiwgIlBCQU5LQS0wNDE2MTAwIiwgIlBCQU5LQS0wODMxMDAwIiwgIlBCQU5LQS0xMTAyMjAwIikKbXV0YW50X2dlbmVzX2xpc3QgPC0gYygiUEJBTktBLTA4MjgwMDAiLCAiUEJBTktBLTEzMDI3MDAiLCAiUEJBTktBLTE0NDc5MDAiLCAiUEJBTktBLTA0MTM0MDAiLCAiUEJBTktBLTA3MTY1MDAiLCAiUEJBTktBLTAxMDI0MDAiLCAgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCiMjIHRoZXNlIGdldCBkZWZpbmVkIGxhdGVyIG9uLCBidXQgYXJlIHJlcGxpY2F0ZWQgYWJvdmUgaGVyZSBmb3IgcGxvdHRpbmcKYXNleHVhbF9lYXJseV9jbHVzdGVycyA8LSBjKDksIDQsIDE1LCA4LCAxLCAxNCwgMiwgMTAsIDMsIDAsIDYsIDUpCmFzZXh1YWxfbGF0ZV9jbHVzdGVycyA8LSBjKDcsIDEyLCAxOCwgMjAsIDIzKQpiaXBvdGVudGlvbmFsX2Vhcmx5X2NsdXN0ZXJzIDwtICMgMD8KYmlwb3RlbnRpYWxfY2x1c3RlcnMgPC0gYygxMSkgCm1hbGVfY2x1c3RlcnMgPC0gYygxNiwgMTMpCmZlbWFsZV9jbHVzdGVycyA8LSBjKDIxLCAyMiwgMTcsIDE5KQoKIyMgY29weSB0aGUgY2x1c3RlcnMgc28geW91IGRvbid0IHBlcm1hbmVudGx5IGVkaXQgdGhlIG1hc3Rlcgp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycwoKIyMgcmVvcmRlciB0aGUgbGV2ZWxzIHNvIHlvdSBjYW4gcGxvdCB0aGUgY2x1dGVycyBhcyB5b3Ugd2lzaApteV9sZXZlbHMgPC0gYyhhc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzLGFzZXh1YWxfbGF0ZV9jbHVzdGVycywgYmlwb3RlbnRpYWxfY2x1c3RlcnMsIG1hbGVfY2x1c3RlcnMsIGZlbWFsZV9jbHVzdGVycykKCiMjIHJlb3JkZXIgdGhlIGxldmVscwp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIDwtIGZhY3Rvcih4ID0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZywgbGV2ZWxzID0gbXlfbGV2ZWxzKQoKIyMgcmVuYW1lIGNsdXN0ZXJzIHNvIHRoYXQgdGhleSBhcmUgaW50dWl0aXZlCiMgdGhpcyB0cmljayBpcyBmcm9tIGhlcmU6IGh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vTWFuaXB1bGF0aW5nX2RhdGEvUmVuYW1pbmdfbGV2ZWxzX29mX2FfZmFjdG9yLwpsZXZlbHModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZykgPC0gbGlzdChBc2V4dWFsXzE9IjkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8yPSI0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMz0iMTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF80ID0gIjgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF81ID0gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzY9ICAiMTQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF83ID0gIjIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF84ID0gIjEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF85ID0gIjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzEwID0gIjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzExID0gIjYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzEyID0gIjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzEzID0gIjciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzE0ID0gIjEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXNleHVhbF8xNSA9ICIxOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFzZXh1YWxfMTYgPSAiMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc2V4dWFsXzE3ID0gIjIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUHJvZ2VuaXRvciA9ICIxMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hbGVfMSA9ICIxNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1hbGVfMiA9ICIxMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZlbWFsZV8xID0gIjIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVtYWxlXzIgPSAiMjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZW1hbGVfMyA9ICIxOSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZlbWFsZV8zID0gIjE3IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgojIyMgQW5ub3RhdGlvbiBzZXQtdXAKCiMjIGV4dHJhY3QgcHNldWRvdGltZSBudW1iZXJzIGFuZCBpZGVudGl0eSBvZiBjZWxscyB0byBhIGRhdGFmcmFtZQpkZl9wdF9pZCA8LSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVssYygib2xkX3B0X3ZhbHVlcyIsICJtb25vY2xlX3NleCIsICJzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nIiwgIlByZWRpY3Rpb24uU3BlYXJtYW4uIiwgIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIildCgojIyBtYWtlIGEgbmV3IGNvbHVtbgpkZl9wdF9pZCRjb2xvdXIgPC0gTkEKCiMjIGFzc2lnbiBiaW5zIHRvIGVhY2ggb2YgdGhlIHZhbHVlcwojIyBoZWxwIGhlcmU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzk5NDY2MzAvY29sb3VyLXBvaW50cy1pbi1hLXBsb3QtZGlmZmVyZW50bHktZGVwZW5kaW5nLW9uLWEtdmVjdG9yLW9mLXZhbHVlcyAKZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfRWFybHkiIHwgZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIkFzZXh1YWxfTGF0ZSIsIF0kY29sb3VyIDwtIGFzLm51bWVyaWMoY3V0KGRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0Vhcmx5IiB8IGRmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJBc2V4dWFsX0xhdGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJNYWxlIiwgXSRjb2xvdXIgPC0gYXMubnVtZXJpYyhjdXQoZGZfcHRfaWRbZGZfcHRfaWQkbW9ub2NsZV9zZXggPT0gIk1hbGUiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCmRmX3B0X2lkW2RmX3B0X2lkJG1vbm9jbGVfc2V4ID09ICJGZW1hbGUiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiRmVtYWxlIiwgXSRvbGRfcHRfdmFsdWVzLGJyZWFrcyA9IDEwMCkpCgpkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJGNvbG91ciA8LSBhcy5udW1lcmljKGN1dChkZl9wdF9pZFtkZl9wdF9pZCRtb25vY2xlX3NleCA9PSAiQmlwb3RlbnRpYWwiLCBdJG9sZF9wdF92YWx1ZXMsYnJlYWtzID0gMTAwKSkKCiMjIG1ha2UgY29sb3VyIHJhbXBzCmFzZXhfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoIiNENUUzRjUiLCAiIzAwNTJjNSIpKQptYWxlX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICJ5ZWxsb3ciLCAiIzAxNmMwMCIpKQpmZW1hbGVfcmFtcCA8LSBjb2xvclJhbXBQYWxldHRlKGMoInllbGxvdyIsICIjYTUyYjFlIikpCmJpcG90X3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICIjZmZlNDAwIikpCgojIyBhc3NpZ24gdmFsdWVzIHRvIGVhY2ggY2x1c3RlcgojIyB0YWtlIHRoZSBtZWFuIG9mIHRoZSBiaW4KZGZfYW5ub3RhdGlvbiA8LSBhZ2dyZWdhdGUoZGZfcHRfaWRbLCAiY29sb3VyIl0sIGxpc3QoZGZfcHRfaWQkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyksIG1lYW4pCiMjIEJFQ0FVU0Ugd2UgaGF2ZSBvcmRlcmVkIHRoZSBjbHVzdGVycyBhbHJlYWR5LCB3ZSBjYW4gc2ltcGx5IHRha2UgdGhlIHJvdyBpbmRleCBmb3IgdGhpcyBiaXQKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gTkEKZGZfYW5ub3RhdGlvblsxOjE3LCBdJGNvbG91ciA8LSBhc2V4X3JhbXAoMTAwKVtkZl9hbm5vdGF0aW9uWzE6MTcsIF0keF0KZGZfYW5ub3RhdGlvblsxOCwgXSRjb2xvdXIgPC0gYmlwb3RfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMTgsIF0keF0KZGZfYW5ub3RhdGlvblsxOToyMCwgXSRjb2xvdXIgPC0gbWFsZV9yYW1wKDEwMClbZGZfYW5ub3RhdGlvblsxOToyMCwgXSR4XQpkZl9hbm5vdGF0aW9uWzIxOjIzLCBdJGNvbG91ciA8LSBmZW1hbGVfcmFtcCgxMDApW2RmX2Fubm90YXRpb25bMjE6MjMsIF0keF0KCiMjIHBsb3QgYW5ub3RhdGlvbiAKIyMgdGhpcyByZWFsbHkgaGVscGVkOiBodHRwczovL3d3dy5iaW9zdGFycy5vcmcvcC8zOTY4MTAvCmgyIDwtIGdncGxvdChkZl9hbm5vdGF0aW9uKSsKICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBHcm91cC4xLCB5ID0gMSksIAogICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgIGZpbGwgPSBkZl9hbm5vdGF0aW9uJGNvbG91ciwKICAgICAgICAgICBjb2wgPSAiI0ZGRkZGRiIsCiAgICAgICAgICAgd2lkdGggPSAxKSsKICAgICAgdGhlbWVfdm9pZCgpKwogICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSMrCiAgICAgI2ZhY2V0X2dyaWQoLn5jb2xvdXIsIHNjYWxlcyA9ICJmcmVlX3giKQogICAgICNsZWdlbmQgPC0gcGxvdF9ncmlkKGdldF9sZWdlbmQoaDIpLCBnZXRfbGVnZW5kKGgxKSwgbmNvbCA9IDEpCiBoMiA8LSBoMiArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICMgICBnZW9tX3BvaW50KGNvbCA9IGRmX3VtYXBfcGxvdCRjb2xvdXIpCiAKIGgxIDwtIGdncGxvdChkZl9hbm5vdGF0aW9uKSsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIHkgPSAxKSwKICAgICAgICAgICAgY29sID0gZGZfYW5ub3RhdGlvbiRjb2xvdXIsCiAgICAgICAgICAgIHNpemUgPSA1KSsKICAgICAgdGhlbWVfdm9pZCgpKwogICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSMrCiAgICAgI2ZhY2V0X2dyaWQoLn5jb2xvdXIsIHNjYWxlcyA9ICJmcmVlX3giKQogICAgICNsZWdlbmQgPC0gcGxvdF9ncmlkKGdldF9sZWdlbmQoaDIpLCBnZXRfbGVnZW5kKGgxKSwgbmNvbCA9IDEpCiBoMSA8LSBoMSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICMgICBnZW9tX3BvaW50KGNvbCA9IGRmX3VtYXBfcGxvdCRjb2xvdXIpCgogIyMgYWRkIHByZWRpY3RlZCB0aW1lIHBvaW50CiAjIyB0YWtlIHRoZSBtZWFuIG9mIHRoZSBiaW4KZGZfYW5ub3RhdGlvbiA8LSBhZ2dyZWdhdGUoZGZfcHRfaWRbLCAiUHJlZGljdGlvbi5TcGVhcm1hbi4iXSwgbGlzdChkZl9wdF9pZCRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSwgbWVhbikKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gTkEKZGZfYW5ub3RhdGlvbiRjb2xvdXIgPC0gdmlyaWRpcygzMDApWyhkZl9hbm5vdGF0aW9uJHgpKjEwXQoKaDMgPC0gZ2dwbG90KGRmX2Fubm90YXRpb24pKwogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IEdyb3VwLjEsIHkgPSAxKSwgCiAgICAgICAgICAgc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgZmlsbCA9IGRmX2Fubm90YXRpb24kY29sb3VyLAogICAgICAgICAgIGNvbCA9ICIjRkZGRkZGIiwKICAgICAgICAgICB3aWR0aCA9IDEpKwogICAgICB0aGVtZV92b2lkKCkrCiAgICAgIHRoZW1lKHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMSwgIm1tIikpIysKICAgICAjZmFjZXRfZ3JpZCgufmNvbG91ciwgc2NhbGVzID0gImZyZWVfeCIpCiAgICAgbGVnZW5kX2gzIDwtIGdldF9sZWdlbmQoaDMpCiBoMyA8LSBoMyArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiAgaDMgPC0gZ2dwbG90KGRhdGEgPSBkZl9hbm5vdGF0aW9uLCAKICAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBHcm91cC4xLCBmaWxsPXgpCiAgICAgICAgICAgICAgKSArCiAgICAgICBnZW9tX2Jhcihjb2wgPSAiI0ZGRkZGRiIsIHdpZHRoID0gMSkrCiAgICAgICB0aGVtZV92b2lkKCkgKwogICAgICAgdGhlbWUocGFuZWwuc3BhY2luZy54ID0gdW5pdCgxLCAibW0iKSkgKwogICAgICAgc2NhbGVfZmlsbF92aXJpZGlzKG9wdGlvbiA9ICdjaXZpZGlzJykKIGxlZ2VuZF9oMyA8LSBnZXRfbGVnZW5kKGgzKQogaDMgPC0gaDMgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiAKICMjIGFkZCBrYXNpYSBkYXRhCiAgIyMgdGFrZSB0aGUgbWVhbiBvZiB0aGUgYmluCmRmX2Fubm90YXRpb24gPC0gYWdncmVnYXRlKGRmX3B0X2lkWywgIlByZWRpY3Rpb24uU3BlYXJtYW4uX0thc2lhIl0sIGxpc3QoZGZfcHRfaWQkc2V1cmF0X2NsdXN0ZXJzX2RvdF9wbG90dGluZyksIG1lYW4pCmRmX2Fubm90YXRpb24kY29sb3VyIDwtIE5BCmRmX2Fubm90YXRpb24kY29sb3VyIDwtIHZpcmlkaXMoMzAwKVsoZGZfYW5ub3RhdGlvbiR4KSoxMF0KCmg0IDwtIGdncGxvdChkZl9hbm5vdGF0aW9uKSsKICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBHcm91cC4xLCB5ID0gMSksIAogICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgIGZpbGwgPSBkZl9hbm5vdGF0aW9uJGNvbG91ciwKICAgICAgICAgICBjb2wgPSAiI0ZGRkZGRiIsCiAgICAgICAgICAgd2lkdGggPSAxKSsKICAgICAgdGhlbWVfdm9pZCgpKwogICAgICB0aGVtZShwYW5lbC5zcGFjaW5nLnggPSB1bml0KDEsICJtbSIpKSsKICAgICBmYWNldF9ncmlkKC5+Y29sb3VyLCBzY2FsZXMgPSAiZnJlZV94IikKICAgICBsZWdlbmQgPC0gcGxvdF9ncmlkKGdldF9sZWdlbmQoaDQpLCBuY29sID0gMSkKICAgIGxlZ2VuZF9oNCA8LSBnZXRfbGVnZW5kKGg0KQogaDQgPC0gaDQgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgogaDQgPC0gZ2dwbG90KGRhdGEgPSBkZl9hbm5vdGF0aW9uLCAKICAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBHcm91cC4xLCBmaWxsPXgpCiAgICAgICAgICAgICAgKSArCiAgICAgICBnZW9tX2Jhcihjb2wgPSAiI0ZGRkZGRiIsIHdpZHRoID0gMSkrCiAgICAgICB0aGVtZV92b2lkKCkgKwogICAgICAgdGhlbWUocGFuZWwuc3BhY2luZy54ID0gdW5pdCgxLCAibW0iKSkgKwogICAgICAgc2NhbGVfZmlsbF92aXJpZGlzKCkKIGxlZ2VuZF9oNCA8LSBnZXRfbGVnZW5kKGg0KQogaDQgPC0gaDQgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgojIyMgUGxvdApkb3RfcGxvdF9tYXJrZXJzIDwtIERvdFBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlcyA9IGMobWFya2VyX2dlbmVzX2xpc3QsIHJldihtdXRhbnRfZ2VuZXNfbGlzdCkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvdC5taW4gPSAwLjAwMDAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXkgPSAnUk5BJykgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgY29vcmRfZml4ZWQoKSArCiAgY29vcmRfZmxpcCgpICsKICAjIGNoYW5nZSBhcHBlYXJhbmNlIGFuZCByZW1vdmUgYXhpcyBlbGVtZW50cywgYW5kIG1ha2Ugcm9vbSBmb3IgYXJyb3dzCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgYW5nbGUgPSA0NSwgaGp1c3Q9MSx2anVzdD0xLCBmYW1pbHkgPSAiQXJpYWwiKSwgCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFjZT0iaXRhbGljIiksIAogICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTYsIGZhbWlseT0iQXJpYWwiLCBjb2xvdXI9ImJsYWNrIiksIAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCAKICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLCAKICAgICAgICBsZWdlbmQuYm94ID0gInZlcnRpY2FsIiwgCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMSwzLDEsMyksICJsaW5lcyIpLCAKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGw9TkEsIHNpemU9MC41KSkgKwogICNjaGFuZ2UgdGhlIGNvbG91cnMKICAjc2NhbGVfY29sb3VyX3ZpcmlkaXMob3B0aW9uID0gImluZmVybm8iLCBndWlkZSA9ICJjb2xvdXJiYXIiLCBuYS52YWx1ZT0id2hpdGUiLCBiZWdpbiA9IDAsIGVuZCA9IDEsIGRpcmVjdGlvbiA9IDEpICsKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgY2hhbmdlIHggYXhpcyBsYWJlbAogICMgbGFicyh4ID0gIk1hcmtlciBHZW5lcyIsIHkgPSAiQ2x1c3RlciIsIHRpdGxlID0gIkV4cHJlc3Npb24gb2YgTWFya2VyIEdlbmVzIGJ5IENsdXN0ZXIiKSAKICBsYWJzKHggPSAiIiwgeSA9ICIiLCB0aXRsZSA9ICIiKSArCiAgIyMgYWRkIGFycm93cwogICNhbm5vdGF0ZSgic2VnbWVudCIsIHggPSA1LjUsIHhlbmQgPSA1LjUsIHkgPSAyMS41LCB5ZW5kID0gMjUsIGNvbG91ciA9ICJncmVlbiIsIHNpemU9MSwgYWxwaGE9MSwgYXJyb3c9YXJyb3cobGVuZ3RoPXVuaXQoMC4zMCwiY20iKSwgdHlwZSA9ICJjbG9zZWQiKSkgKwogICNhbm5vdGF0ZSgic2VnbWVudCIsIHggPSA1LjUsIHhlbmQgPSA1LjUsIHkgPSAxNi41LCB5ZW5kID0gMjEuNSwgY29sb3VyID0gInJlZCIsIHNpemU9MSwgYWxwaGE9MSwgYXJyb3c9YXJyb3cobGVuZ3RoPXVuaXQoMC4zMCwiY20iKSwgdHlwZSA9ICJjbG9zZWQiKSkgKwogICNhbm5vdGF0ZSgic2VnbWVudCIsIHggPSA1LjUsIHhlbmQgPSA1LjUsIHkgPSAwLCB5ZW5kID0gMTUuNSwgY29sb3VyID0gImdyZXkiLCBzaXplPTEsIGFscGhhPTEsIGFycm93PWFycm93KGxlbmd0aD11bml0KDAuMzAsImNtIiksIHR5cGUgPSAiY2xvc2VkIikpICsKICAjIyBhbm5vdGF0ZSBhc2V4CiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IChsZW5ndGgoYyhhc2V4dWFsX2Vhcmx5X2NsdXN0ZXJzLCBhc2V4dWFsX2xhdGVfY2x1c3RlcnMpKSswLjUpKSwgc2l6ZSA9IDAuNSwgbGluZXR5cGU9ICdkYXNoZWQnKSArCiAgIyMgYW5ub3RhdGUgYmlwb3RlbnRpYWwKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gKGxlbmd0aChjKGFzZXh1YWxfZWFybHlfY2x1c3RlcnMsIGFzZXh1YWxfbGF0ZV9jbHVzdGVycywgYmlwb3RlbnRpYWxfY2x1c3RlcnMpKSswLjUpKSwgc2l6ZSA9IDAuNSwgbGluZXR5cGU9ICdkYXNoZWQnKSArCiAgIyMgYW5ub3RhdGUgc2V4ZXMKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gKGxlbmd0aChjKGFzZXh1YWxfZWFybHlfY2x1c3RlcnMsIGFzZXh1YWxfbGF0ZV9jbHVzdGVycywgYmlwb3RlbnRpYWxfY2x1c3RlcnMsIG1hbGVfY2x1c3RlcnMpKSswLjUpKSwgc2l6ZSA9IDAuNSwgbGluZXR5cGU9ICdkYXNoZWQnKSArCiAgIyMgY2hhbmdlIGxhYmVsIG9uIGJvdHRvbSBvZiBwbG90IHNvIHdlIGNhbiBpbmRpY2F0ZSBtYXJrZXJzCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSByZXYoYygiZ2QxIiwgIm1kMSIsICJtZDIiLCAibWQzIiwgIm1kNCIsICJtZDUiLCAiZmQxIiwgImZkMiIsICJmZDMiLCAiZmQ0IiwgIm1zcDgiLCAibXNwMSIsICJtZzEiLCAiY2NwMiIsICJhcDJnIikpKSArCiAgIyMgY2hhbmdlIGxhYmVsIG9uIGJvdHRvbSBvZiBwbG90IHNvIHdlIGNhbiBpbmRpY2F0ZSBtYXJrZXJzCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSBjKCJBc2V4dWFsIDEiLCAiQXNleHVhbCAyIiAsICJBc2V4dWFsIDMiLCAiQXNleHVhbCA0IiwgIkFzZXh1YWwgNSIsICJBc2V4dWFsIDYiLCAiQXNleHVhbCA3IiwgIkFzZXh1YWwgOCIsICAiQXNleHVhbCA5IiwgIkFzZXh1YWwgMTAiLCAiQXNleHVhbCAxMSIsICJBc2V4dWFsIDEyIiwgIkFzZXh1YWwgMTMiLCAiQXNleHVhbCAxNCIsICJBc2V4dWFsIDE1IiwgIkFzZXh1YWwgMTYiLCAiQXNleHVhbCAxNyIsICJQcm9nZW5pdG9yIiwgIk1hbGUgMSIsICJNYWxlIDIiLCAiRmVtYWxlIDEiLCAiRmVtYWxlIDIiLCAiRmVtYWxlIDMiKSkgKwogICMjIGNoYW5nZSBuYW1lIG9mIGxlZ2VuZHMKICBndWlkZXMoY29sPWd1aWRlX2NvbG9yYmFyKHRpdGxlID0gJ1NjYWxlZCBBdmVyYWdlIEV4cHJlc3Npb24nKSwKICAgICAgICAgc2l6ZT1ndWlkZV9sZWdlbmQoIiUgb2YgY2VsbHMgZXhwcmVzc2luZyIpKQoKIyMgdmlldwojcHJpbnQoZG90X3Bsb3RfbWFya2VycykKCnBsb3QgPC0gcGxvdF9ncmlkKGg0LCBoMywgaDEsIGRvdF9wbG90X21hcmtlcnMsIGFsaWduID0gInYiLCBuY29sID0gMSwgYXhpcyA9ICJ0YiIsIHJlbF9oZWlnaHRzID0gYygwLjUsIDAuNSwgMC41LCAxOCkpIAoKZG90X3Bsb3QgPC0gcGxvdF9ncmlkKHBsb3QsIGxlZ2VuZF9oMywgbGVnZW5kX2g0LCBucm93ID0gMSwgcmVsX3dpZHRocyA9IGMoMTAsIDEuNSwgMS41KSkKCmRvdF9wbG90CmBgYAoKc2F2ZQpgYGB7cn0KZ2dzYXZlKCIuLi9pbWFnZXNfdG9fZXhwb3J0L2RvdF9wbG90X2FsbC5wbmciLCBwbG90ID0gZG90X3Bsb3QsIGRldmljZSA9ICJwbmciLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDI5LjcsIGhlaWdodCA9IDIxLCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgpNYWtlIGluZGl2aWR1YWwgcGxvdHMgaGlnaGxpZ2h0aW5nIHdoZXJlIGNlbGxzIGluIGVhY2ggY2x1c3RlciBmYWxsCmBgYHtyLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMjIGZvciBsb29wIHdoaWNoIHRha2VzIGVhY2ggY2x1c3RlciBhbmQgbWFrZXMgYSBsaXN0IG9mIGNlbGxzIGFuZCB0aGVuIHBsb3RzIGEgaGlnaGxpZ2h0ZWQgcGxvdCBhbmQgYWRkcyBpdCB0byBhIGxpc3QKCiMjIG1ha2UgYSBibGFuayBsaXN0Cmxpc3RfVU1BUHNfYnlfY2x1c3RlciA8LSB2ZWN0b3IobW9kZSA9ICJsaXN0IiwgbGVuZ3RoID0gbGVuZ3RoKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnNfZG90X3Bsb3R0aW5nKSkpCgojIyBmb3IgbG9vcApmb3IoaSBpbiBzZXFfYWxvbmcobGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpKSl7CiAgIyMgbWFrZSBhIGxpc3Qgb2YgY2VsbHMKICBsaXN0X29mX2NlbGxzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhW3doaWNoKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcgPT0gbGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpW2ldKSwgXSkKICB1bWFwX3Bsb3QgPC0gRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBsYWJlbCA9IEZBTFNFLCByZXBlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjEsIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3Rfb2ZfY2VsbHMsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikgKwogICAgIyMgZml4IGNvb3JkaW5hdGVzCiAgICBjb29yZF9maXhlZCgpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjRDNEM0QzIiwgIiMxRDE1NjQiKSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUobGV2ZWxzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcpW2ldKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQogICMjIGFkZCB0byB0aGUgbGlzdAogIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbaV1dIDwtIHVtYXBfcGxvdAp9CgojIyBjaGVjayBudW1iZXIgb2YgY2x1c3RlcnMKbGVuZ3RoKGxpc3RfVU1BUHNfYnlfY2x1c3RlcikKYGBgCgpwbG90CmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIyB0aGlzIGZ1bmN0aW9uIHdyaXRlcyB0aGUgbmV4dCBiaXQgb2YgY29kZSBmb3IgeW91CiMjIHB1dCBpdCBpbnRvIHRoZSBjb25zb2xlIGFuZCBwYXN0ZSB0aGUgcmVzcG9uc2UKI3Bsb3R5IDwtIGMoKQojZm9yKGkgaW4gc2VxX2Fsb25nKGxldmVscyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRzZXVyYXRfY2x1c3RlcnMpKSl7CiMgIHBsb3R5IDwtIHBhc3RlMChwbG90eSwgImxpc3RfVU1BUHNfYnlfY2x1c3RlcltbIiwgaSwgIl1dIiwgIiArICIpCiN9CgojIyBwbG90CmNvbXBvc2l0ZV9wbG90IDwtIHBsb3RfZ3JpZChsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzFdXSwgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syXV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbM11dLCBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzRdXSwgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s1XV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNl1dLCBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzddXSwgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s4XV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOV1dLCBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEwXV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTFdXSwgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxMl1dLCBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEzXV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTRdXSwgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxNV1dLCBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE2XV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMTddXSwgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1sxOF1dLCBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE5XV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMjBdXSwgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1syMV1dLCBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIyXV0sIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMjNdXSwgbmNvbCA9IDgpCgpjb21wb3NpdGVfcGxvdApgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9jbHVzdGVyc19jb21wb3NpdGVfcGxvdC5wbmciLCBwbG90ID0gY29tcG9zaXRlX3Bsb3QsIGRldmljZSA9ICJwbmciLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDIxLCBoZWlnaHQgPSAxMCwgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKIyA5LiBTdWJzZXQgc2V4dWFsIGNlbGxzIHsudGFic2V0fQoKTWFrZSBhIHN1YnNldHRlZCBTZXVyYXQgb2JqZWN0IG9mIHNleHVhbCBjZWxscy4gCgpJbmNsdWRlIHRoZSBwcmUtYnJhbmNoIHRvbyBhcyB3ZWxsIGFzIGFueSB3ZWlyZCBjbHVzdGVycyB0aGF0IG1heSBoYXZlIGNsdXN0ZXJlZCBvdXQuIAoKaXQncyBiZWVuIGEgd2hpbGUgc2luY2Ugd2UgbG9va2VkIGF0IHRoZSBjbHVzdGVycyBzbyBsZXQncyBjaGVjayB0aGVtIG91dCBhZ2FpbjoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMjIFBsb3QKRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gRkFMU0UsIHB0LnNpemUgPSAwLjA1LCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIpICsgY29vcmRfZml4ZWQoKQoKIyMgcGxvdApsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzFdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbMl1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1szXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzRdXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbNV1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzddXSArIGxpc3RfVU1BUHNfYnlfY2x1c3RlcltbOF1dICsgbGlzdF9VTUFQc19ieV9jbHVzdGVyW1s5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzExXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzEzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE0XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE1XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE2XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE3XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE4XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzE5XV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIwXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIxXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIyXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzIzXV0gKyBsaXN0X1VNQVBzX2J5X2NsdXN0ZXJbWzI0XV0KYGBgCgojIyMgRGVmaW5lIGNlbGxzIGFuZCBzdWJzZXQKYGBge3J9CmFzZXh1YWxfZWFybHlfY2x1c3RlcnMgPC0gYyg5LCA0LCAxNSwgOCwgMSwgMTQsIDIsIDEwLCAzLCAwLCA2LCA1KQphc2V4dWFsX2xhdGVfY2x1c3RlcnMgPC0gYyg3LCAxMiwgMTgsIDIwLCAyMykKYmlwb3RlbnRpb25hbF9lYXJseV9jbHVzdGVycyA8LSAjIDA/CmJpcG90ZW50aWFsX2NsdXN0ZXJzIDwtIGMoMTEpIAptYWxlX2NsdXN0ZXJzIDwtIGMoMTYsIDEzKQpmZW1hbGVfY2x1c3RlcnMgPC0gYygyMSwgMjIsIDE3LCAxOSkKCiMjIGRlZmluZSBjZWxscwpjZWxsX25hbWVzX3N1YnNldF9tb25vY2xlX2lkcyA8LSByb3duYW1lcyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YVt0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkQG1ldGEuZGF0YSRtb25vY2xlX3NleCAlaW4lIGMoIkFzZXh1YWxfRWFybHkiLCAiQmlwb3RlbnRpYWwiLCAiTWFsZSIsICJGZW1hbGUiKSwgXSkKCiMjIDMsIDAsIDYsIDUgYXJlIGVhcmx5IGNsdXN0ZXJzIG9mIGFzZXh1YWxzIGJlZm9yZSB0aGUgYnJhbmNoCmNlbGxfbmFtZXNfc3Vic2V0X2NsdXN0ZXJfaWRzIDwtIHJvd25hbWVzKHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhW3RlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycyAlaW4lIGMobWFsZV9jbHVzdGVycywgZmVtYWxlX2NsdXN0ZXJzLCBiaXBvdGVudGlhbF9jbHVzdGVycywgMywgMCwgNiwgNSksIF0pCgpjZWxsX25hbWVzX3N1YnNldF9pbnRlcnNlY3QgPC0gaW50ZXJzZWN0KGNlbGxfbmFtZXNfc3Vic2V0X21vbm9jbGVfaWRzLCBjZWxsX25hbWVzX3N1YnNldF9jbHVzdGVyX2lkcykKCiMjIHN1YnNldCBjZWxscyBpbnRvIG5ldyBvYmplY3QKdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXggPC0gc3Vic2V0KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGNlbGxzID0gY2VsbF9uYW1lc19zdWJzZXRfaW50ZXJzZWN0KQpgYGAKCiMjIyBpbnNwZWN0L2NoZWNrCmBgYHtyfQojIyBpbnNwZWN0IG9iamVjdAp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleAoKIyMgbG9vayBhdCBvcmlnaW5hbCBVTUFQCkRpbVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBzcGxpdC5ieSA9ICJleHBlcmltZW50IiwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiKSArIGNvb3JkX2ZpeGVkKCkKYGBgCgojIyMgUmVtb3ZlIGNvbnRhbWluYW50IGFzZXh1YWwgY2VsbHMKCndlIHdhbnQgdG8gcmVtb3ZlOgpgYGB7cn0KIyMgbG9vayBhdCBvcmlnaW5hbCBVTUFQCnBsb3Rfc2V4dWFsX3N1YnNldHRpbmcgPC0gRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFRSVUUsIHB0LnNpemUgPSAwLjEsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikgKyAKICBjb29yZF9maXhlZCgpICsgCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IC0xLCBhbHBoYSA9IDUpKQoKcGxvdF9zZXh1YWxfc3Vic2V0dGluZwpgYGAKCmBgYHtyfQojIyBleHRyYWN0IGNlbGwgZW1iZWRkaW5ncwpkZl9zZXhfY2VsbF9lbWJlZGRpbmdzIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXhAcmVkdWN0aW9uc1tbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzKQoKIyMgc3Vic2V0IGFueXRoaW5nIGxvd2VyIHRoYW4gLTAuOCBpbiBVTUFQIDIgYW5kIC0wLjEgaW4gVU1BUCAxCnJlbW92ZV9jZWxscyA8LSByb3cubmFtZXMoZGZfc2V4X2NlbGxfZW1iZWRkaW5nc1t3aGljaChkZl9zZXhfY2VsbF9lbWJlZGRpbmdzJFVNQVBfMSA8IC0xKSwgXSkKCiMjIHBsb3QgdGhlc2UgY2VsbHMKRGltUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgbGFiZWwgPSBGQUxTRSwgcmVwZWwgPSBUUlVFLCBwdC5zaXplID0gMC4xLCBjZWxscy5oaWdobGlnaHQgPSByZW1vdmVfY2VsbHMsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIikgKyAKICBjb29yZF9maXhlZCgpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjMDAwMDAwIiwgIiNmNTRlMWUiKSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImNlbGxzIGhpZ2hsaWdodGVkIHdpbGwgYmUgcmVtb3ZlZCIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKIyMgRmluYWwgU3Vic2V0CmBgYHtyfQojIyBtYWtlIGtlZXAgY2VsbHMgZnJvbSB0aGUgcmVtb3ZlX2NlbGxzCiMjIG1ha2UgdGhlIG5vdCBpbiBmdW5jdGlvbgonJW5pJScgPC0gTmVnYXRlKCclaW4lJykKa2VlcF9jZWxscyA8LSBjb2xuYW1lcyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleClbd2hpY2goY29sbmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgpICVuaSUgcmVtb3ZlX2NlbGxzKV0KCiMjIHN1YnNldAp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCA8LSBzdWJzZXQodGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgsIGNlbGxzID0ga2VlcF9jZWxscykKCiMjIGluc3BlY3QKdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXgKYGBgCgpjb3B5IG9sZCBjbHVzdGVycyBvdmVyCmBgYHtyfQojIyBjb3B5IG9sZCBjbHVzdGVycwp0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCA8LSBBZGRNZXRhRGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLnNleCwgdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5zZXhAbWV0YS5kYXRhJHNldXJhdF9jbHVzdGVycywgY29sLm5hbWUgPSAicG9zdF9pbnRlZ3JhdGlvbl9jbHVzdGVycyIpCmBgYAoKIyAxMC4gU2V4IGFzc2lnbm1lbnQgb2YgbXV0YW50cyAKCiMjIEEuIFNldXJhdCBNZXRob2QKCmBgYHtyfQojIyBmaW5kIHRyYW5zZmVyIGFuY2hvcnMKRGVmYXVsdEFzc2F5KHRlbnguanVzdHd0LmludGVncmF0ZWQpIDwtICJpbnRlZ3JhdGVkIgptZXJnZS5hbmNob3JzIDwtIEZpbmRUcmFuc2ZlckFuY2hvcnMocmVmZXJlbmNlID0gdGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgcXVlcnkgPSBHQ1NLT19tdXRhbnRzLCAKICAgIGRpbXMgPSAxOjMwKQoKIyMgdHJhbnNmZXIgZGF0YSBiZXR3ZWVuIHJlZiBhbmQgcXVlcnkKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IG1lcmdlLmFuY2hvcnMsIHJlZmRhdGEgPSB0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkJHNldXJhdF9jbHVzdGVyc19kb3RfcGxvdHRpbmcsIAogICAgZGltcyA9IDE6MzApCgojIyBhZGQgbWV0YSBkYXRhIHRvIG9iamVjdApHQ1NLT19tdXRhbnRzIDwtIEFkZE1ldGFEYXRhKEdDU0tPX211dGFudHMsIG1ldGFkYXRhID0gcHJlZGljdGlvbnMpCgojIyBuZXcgb2JqZWN0IGZyb20gdGhpcwptdXRhbnRfc2V1cmF0IDwtIEdDU0tPX211dGFudHMKCiMjIGxvb2sgYXQgYnJlYWtkb3duIG9mIG11dGFudCBieSBkZXNpZ25hdGlvbgpkZiA8LSBhcy5kYXRhLmZyYW1lKG11dGFudF9zZXVyYXRAbWV0YS5kYXRhKQp0YWJsZShkZiRwcmVkaWN0ZWQuaWQsIGRmJGlkZW50aXR5X25hbWVfdXBkYXRlZCkKYGBgCgpgYGB7cn0KIyMgc2VlIGhvdyB0aGlzIG92ZXJsYXBzIHdpdGggZmx1b3Jlc2NlbmNlIHNvcnRlZCBvbiBmb3IgODIwIHRvIGNvbmZpcm0gYWNjdXJhY3kKZGZfODIwIDwtIGRmW2RmJGdlbmV0aWNfYmFja2dyb3VuZCA9PSJQQkFOS0FfODIwIiwgXQp0YWJsZShkZl84MjAkcHJlZGljdGVkLmlkLCBkZl84MjAkZmx1b3Jlc2VuY2Vfc29ydGVkX29uKQpgYGAKCmluc3BlY3QgZ2QxCmBgYHtyfQpkZlt3aGljaChkZiRwcmVkaWN0ZWQuaWQgPT0gIkZlbWFsZV8xIiAmIGRmJGlkZW50aXR5X25hbWVfdXBkYXRlZCA9PSAiZ2QxIiksIF1bLCAxMTg6MTQ2XQpgYGAKCgpDYWxjdWxhdGUgc2V4IHJhdGlvcwpgYGB7cn0KIyMgdXNlIGRlc2lnbmF0aW9ucyBhYm92ZSBmb3Igc2V4ZXMKbWFsZV9jZWxscyA8LSByb3duYW1lcyhtdXRhbnRfc2V1cmF0QG1ldGEuZGF0YVttdXRhbnRfc2V1cmF0QG1ldGEuZGF0YSRwcmVkaWN0ZWQuaWQgPT0gIk1hbGUiLCBdKQpmZW1hbGVfY2VsbHMgPC0gcm93bmFtZXMobXV0YW50X3NldXJhdEBtZXRhLmRhdGFbbXV0YW50X3NldXJhdEBtZXRhLmRhdGEkcHJlZGljdGVkLmlkID09ICJGZW1hbGUiLCBdKQpzczJfbXV0YW50c19maW5hbF9tYWxlIDwtIHN1YnNldChtdXRhbnRfc2V1cmF0LCBjZWxscyA9IG1hbGVfY2VsbHMpCnNzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZSA8LSBzdWJzZXQobXV0YW50X3NldXJhdCwgY2VsbHMgPSBmZW1hbGVfY2VsbHMpCgojIyBpbnNwZWN0CnNzMl9tdXRhbnRzX2ZpbmFsX21hbGUKc3MyX211dGFudHNfZmluYWxfZmVtYWxlCmBgYAoKYGBge3J9CiMjIGNhbGN1bGF0ZSBzZXggcmF0aW9zCiMjc3Vic2V0IG91dCBILCBzb3J0ZWQgY2VsbHM6CmRmX21hbGUgPC0gc3MyX211dGFudHNfZmluYWxfbWFsZUBtZXRhLmRhdGFbc3MyX211dGFudHNfZmluYWxfbWFsZUBtZXRhLmRhdGEkZXhjbHVkZV9mb3Jfc2V4X3JhdGlvID09IEZBTFNFLF0KCmRpbShkZl9tYWxlKQoKZGZfZmVtYWxlIDwtIHNzMl9tdXRhbnRzX2ZpbmFsX2ZlbWFsZUBtZXRhLmRhdGFbc3MyX211dGFudHNfZmluYWxfZmVtYWxlQG1ldGEuZGF0YSRleGNsdWRlX2Zvcl9zZXhfcmF0aW8gPT0gRkFMU0UsXQoKZGltKGRmX2ZlbWFsZSkKCiMjIG1ha2UgZGF0YWZyYW1lCmRmX3NleF9yYXRpbyA8LSBtZXJnZSgKICBhcy5kYXRhLmZyYW1lKHRhYmxlKGRmX21hbGUkc3ViX25hbWVfdXBkYXRlZCkpLCAKICBhcy5kYXRhLmZyYW1lKHRhYmxlKGRmX2ZlbWFsZSRzdWJfbmFtZV91cGRhdGVkKSksIAogIGJ5ID0gIlZhcjEiLCBhbGw9VFJVRSkKCiMgb3IgdXNlIGlkZW50aXR5X3VwZGF0ZWQKCiMjIGFkZCBuYW1lcwpuYW1lcyhkZl9zZXhfcmF0aW8pIDwtIGMoImdlbm90eXBlIiwgIm1hbGUiLCAiZmVtYWxlIikKCiMjIGNoYW5nZSB0aGUgTkFzIHRvIDAKZGZfc2V4X3JhdGlvW2lzLm5hKGRmX3NleF9yYXRpbyldIDwtIDAKCiMjIGNvbGxhcHNlIDgyMCB3aWxkLXR5cGVzIHRvZ2V0aGVyCmNvbWJpbmVkX20gPC0gZGZfc2V4X3JhdGlvW2RmX3NleF9yYXRpbyRnZW5vdHlwZSA9PSAiV1QtODIwXzNfNSIsIF0kbWFsZSArIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMCIsIF0kbWFsZQpjb21iaW5lZF9mIDwtIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMF8zXzUiLCBdJGZlbWFsZSArIGRmX3NleF9yYXRpb1tkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMCIsIF0kZmVtYWxlCmRmX3NleF9yYXRpbyA8LSByYmluZChkZl9zZXhfcmF0aW8sIGMoIldULTgyMC1jb21iaW5lZCIsIGNvbWJpbmVkX20sIGNvbWJpbmVkX2YpKQojIHJlbW92ZSBvbGQgcm93cwpkZl9zZXhfcmF0aW8gPC0gZGZfc2V4X3JhdGlvWy13aGljaChkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPT0gIldULTgyMF8zXzUiIHwgZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC04MjAiKSwgXQojIG5lZWQgdG8gbWFrZSBudW1lcmljIGFnYWluCmRmX3NleF9yYXRpbyRtYWxlIDwtIGFzLm51bWVyaWMoZGZfc2V4X3JhdGlvJG1hbGUpCmRmX3NleF9yYXRpbyRmZW1hbGUgPC0gYXMubnVtZXJpYyhkZl9zZXhfcmF0aW8kZmVtYWxlKQpkZl9zZXhfcmF0aW8kZ2Vub3R5cGUgPC0gYXMuY2hhcmFjdGVyKGRmX3NleF9yYXRpbyRnZW5vdHlwZSkKIyBhZGQgbmFtZSBmb3IgV1QgY29tYmluZWQKZGZfc2V4X3JhdGlvJGdlbm90eXBlWzE3XSA8LSAiV1QtODIwLWNvbWJpbmVkIgoKIyMgY2FsY3VsYXRlIHNleCByYXRpbwpkZl9zZXhfcmF0aW8kc2V4X3JhdGlvIDwtIChkZl9zZXhfcmF0aW8kbWFsZSArIDAuMSkvKGRmX3NleF9yYXRpbyRmZW1hbGUgKyAwLjEpCgojIyBsb2cgc2V4IHJhdGlvCmRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nIDwtIGxvZzEwKGRmX3NleF9yYXRpbyRzZXhfcmF0aW8pCgojI3ZpZXcKZGZfc2V4X3JhdGlvCmBgYAoKYGBge3J9CiMjIHJlbW92ZSBXVC0yIGJlY2F1c2UgaXQgaXMgcmVhbGx5IGluYXBwcm9wcmlhdGUgdG8gaGF2ZSBhIHNleCByYXRpbyBmb3IgdGhpczoKZGZfc2V4X3JhdGlvIDwtIGRmX3NleF9yYXRpb1std2hpY2goZGZfc2V4X3JhdGlvJGdlbm90eXBlID09ICJXVC1tZDUiKSxdCmBgYAoKcGxvdApgYGB7ciwgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aCA9IDZ9CmxpYnJhcnkobGF0ZXgyZXhwKSAjIHNvIHlvdSBjYW4gcGxvdCB0aGUgZnJhY3Rpb24sIGl0J3Mgb24gQ1JBTiBgaW5zdGFsbC5wYWNrYWdlcygibGF0ZXgyZXhwIilgCgojIyBtYWtlIGV4dHJhIGNvbHVtbiBmb3IgcGxvdHRpbmcgYWVzdGhldGljczoKZGZfc2V4X3JhdGlvJGFib3ZlIDwtIGRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nID4gMAoKIyMgbWFrZSBleHRyYSBjb2x1bW4gd2l0aCByYXRpbyBpbiBpdDoKZGZfc2V4X3JhdGlvJGdlbm90eXBlX3dpdGhfbiA8LSBwYXN0ZTAoZGZfc2V4X3JhdGlvJGdlbm90eXBlLCAiICgiLCBkZl9zZXhfcmF0aW8kbWFsZSwgIi8iLCBkZl9zZXhfcmF0aW8kZmVtYWxlLCAiKSIpCgojIyByZW9yZGVyIGdlbm90eXBlIHNvIGl0IGlzIGluIHRoZSBjb3JyZWN0IG9yZGVyIGZvciBwbG90dGluZwpkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uIDwtIGZhY3RvcihkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uLCBsZXZlbHMgPSBkZl9zZXhfcmF0aW8kZ2Vub3R5cGVfd2l0aF9uW29yZGVyKGRmX3NleF9yYXRpbyRzZXhfcmF0aW9fbG9nKV0pCgojIyBwbG90CnNleF9yYXRpb19wbG90IDwtIGdncGxvdChkZl9zZXhfcmF0aW8sIGFlcyhzZXhfcmF0aW9fbG9nLCBnZW5vdHlwZV93aXRoX24sIGNvbG9yID0gYWJvdmUpKSArCiAgICAgICMjIGFkZCB0aGUgbGluZXMgZm9yIHRoZSBsb2xsaXBvcCBwbG90CiAgICAgIGdlb21fc2VnbWVudChhZXMoeCA9IDAsIHkgPSBnZW5vdHlwZV93aXRoX24sIHhlbmQgPSBzZXhfcmF0aW9fbG9nLCB5ZW5kID0gZ2Vub3R5cGVfd2l0aF9uKSwgY29sb3IgPSAiZ3JleTUwIikgKwogICAgICAjIyBhZGQgdGhlIHBvaW50cyBmb3IgdGhlIGxvbGxpcG9wIHBsb3QKICAgICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IDQpKSArCiAgICAgICMjIGFkZCB0aGUgd2lsZC10eXBlIHJlY3RhbmdsZQogICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49IC0wLjIzMTgyNDc4LCB4bWF4ID0gMS4wMDEwNTc5NywgeW1pbj0tSW5mICwgeW1heD1JbmYsIGFscGhhPTAuNCwgY29sb3I9TkEsbGluZXR5cGUgPSAyLCBmaWxsPSIjOTk5OTk5IikgKwogICAgICAjIyBtYWtlIHByZXR0aWVyCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNiwgZmFtaWx5PSJBcmlhbCIpKSArIAogICAgICAjIyBjaGFuZ2UgYXhpcyBsYWJlbHMKICAgICAgbGFicyh5ID0gVGVYKCIkR2Vub3R5cGVcIFxcbGVmdChcXGZyYWN7bl97bWFsZX19e25fe2ZlbWFsZX19XFxyaWdodCkkIikpICsKICAgICAgI2xhYnMoeSA9IGV4cHJlc3Npb24ocGFzdGUoIkdlbm90eXBlIiwgZ3JvdXAoIigiLCBmcmFjKHBhc3RlKCJuIG1hbGUiKSwgIm4gZmVtYWxlIiksICIpIikpKSkgKwogICAgICB4bGFiKGV4cHJlc3Npb24ocGFzdGUoIlNleCBSYXRpbyAoIiwgbG9nWzEwXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCgiKCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJhYyhwYXN0ZSgibiBtYWxlICsgMC4xIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIm4gZmVtYWxlICsgMC4xIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIpIiksICIpIiApKSkgKwogICAgICAjIyBjaGFuZ2UgY29sb3VycyBvZiBsb2xsaXBvcHMKICAgICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCIjYTUyYjFlIiwgIiMwMTZjMDAiKSkgKwogICAgICAjIyBhbm5vdGF0ZSBwaGVub3R5cGVzCiAgICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSA1LjUpKSAjKwogICAgICAjZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDE0LjUpKQoKcHJpbnQoc2V4X3JhdGlvX3Bsb3QpCgojIyMgQ0hBTkdFIFRPIEJJRyBCUkFDS0VUIEhFUkU6IGh0dHBzOi8vd3d3Lm92ZXJsZWFmLmNvbS9sZWFybi9sYXRleC9CcmFja2V0c19hbmRfUGFyZW50aGVzZXMgCgojcGFzdGUoIlNleCBSYXRpbyIsICJcbiIsICJsb2cxMCgobiBtYWxlICsgMC4xKS8obiBmZW1hbGUgKyAwLjEpKSIpCiN0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTYsIGZhbWlseT0iQXJpYWwiKSkKCiMjIGZyYWN0aW9uIHRpdGxlczogaHR0cHM6Ly9ncm91cHMuZ29vZ2xlLmNvbS9mb3J1bS8jIXRvcGljL2dncGxvdDIvYmdOUm5aODJoSlkgCiMjIGh0dHBzOi8vdWMtci5naXRodWIuaW8vbG9sbGlwb3AKCiNnZ3NhdmUoZmlsZW5hbWUgPSAiLi4vaW1hZ2VzX3RvX2V4cG9ydC9zZXhfcmF0aW9fcGxvdC5wbmciLCBkZXZpY2UgPSAicG5nIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA3LCB1bml0cyA9ICJpbiIpCmBgYAoKIyMgQi4gU0NNQVAgTWV0aG9kCgojIyMgQnVpbGQgdGhlIGluZGV4CgpgYGB7cn0KIyMjIE1ha2luZyBhbiBvcnRob2xvZyByZWZlcmVuY2UgaW5kZXgKCiMjIGxvYWQgaW4gbWNhIGRhdGEKI2NvdW50cyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfY291bnRzLmNzdiIsIHJvdy5uYW1lcyA9IDEpCiNwaGVubyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfcGhlbm8uY3N2IikKI2dncGxvdChwaGVubywgYWVzKHg9UEMyXzNkLCB5ID0gUEMzXzNkLGNvbG91cj1hYnNjbHVzdDMpKSArIGdlb21fcG9pbnQoKQoKIyMgbG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShzY21hcCkgI2h0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvaHRtbC9zY21hcC5odG1sIApsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KSAjCgojcHJlcCB0aGUgU0NFLCBpZiB3YXMgb3JpZ2luYWxseSBhIFN1ZXJhdCBvYmplY3QgbmVlZCB0aGUgZGZzIHRvIGJlIHJlZ3VsYXIgbWF0cmljZXMKI3BiX2ZpbHRlcmVkX3NjZV9vcnRoIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoWywgY29sRGF0YShwYl9maWx0ZXJlZF9zY2Vfb3J0aCkkYWJzY2x1c3QzICE9ICI4Il0KI3NjZSA8LSBwYl9maWx0ZXJlZF9zY2Vfb3J0aAojcGNhIDwtIHBsb3RQQ0Eoc2NlKQojcGNzIDwtIHBjYSRkYXRhCiN0YWJsZShyb3duYW1lcyhwY3MpPT1jb2xuYW1lcyhzY2UpKQojY29sRGF0YShzY2UpIDwtIGNiaW5kKGNvbERhdGEoc2NlKSwgcGNzKQojcm93RGF0YShzY2UpJGZlYXR1cmVfc3ltYm9sIDwtIHJvd0RhdGEoc2NlKSRnZW5lCgojIyBleHRyYWN0IGRhdGEgZnJvbSBTZXVyYXQKI2NlbGxzX3RlbnggPC0gcm93bmFtZXModGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGFbd2hpY2godGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEkZXhwZXJpbWVudCA9PSAidGVueF81ayIpLCBdKQojdGVueC5qdXN0d3QuaW50ZWdyYXRlZC4xMGsgPC0gc3Vic2V0KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGNlbGxzID0gY2VsbHNfdGVueCkKY291bnRzID0gYXMubWF0cml4KEdldEFzc2F5RGF0YSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBzbG90ID0gImNvdW50cyIsIGFzc2F5ID0gIlJOQSIpKQpwaGVubyA9IGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEBtZXRhLmRhdGEpCgojIyBhZGQgVU1BUCBjb29yZGluYXRlcwpkZl9zZXhfY2VsbF9lbWJlZGRpbmdzIDwtIGFzLmRhdGEuZnJhbWUodGVueC5qdXN0d3QuaW50ZWdyYXRlZEByZWR1Y3Rpb25zW1sidW1hcCJdXUBjZWxsLmVtYmVkZGluZ3MpCnBoZW5vIDwtIGNiaW5kKHBoZW5vLCBkZl9zZXhfY2VsbF9lbWJlZGRpbmdzKQoKIyMgU2V0IHVwIG9iamVjdApzY2UgPC0gU2luZ2xlQ2VsbEV4cGVyaW1lbnQobGlzdChjb3VudHM9Y291bnRzKSwKICAgIGNvbERhdGE9RGF0YUZyYW1lKGxhYmVsPXBoZW5vKSwKICAgIHJvd0RhdGE9RGF0YUZyYW1lKGZlYXR1cmVfc3ltYm9sPXJvd25hbWVzKGNvdW50cykpKQpzY2UKCiMjIG1hbnVhbCBsb2dnaW5nCiNjb3VudHNfMSA8LSBhc3NheShzY2UsICJjb3VudHMiKQojbGlic2l6ZXMgPC0gY29sU3Vtcyhjb3VudHNfMSkKI3NpemUuZmFjdG9ycyA8LSBsaWJzaXplcy9tZWFuKGxpYnNpemVzKQojbG9nY291bnRzKHNjZSkgPC0gbG9nMih0KHQoY291bnRzXzEpL3NpemUuZmFjdG9ycykgKyAxKQojY291bnRzKHNjZSkgPC0gYXMubWF0cml4KGNvdW50cyhzY2UpKQojbG9nY291bnRzKHNjZSkgPC0gYXMubWF0cml4KGxvZ2NvdW50cyhzY2UpKQpsb2djb3VudHMoc2NlKSA8LSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKHRlbnguanVzdHd0LmludGVncmF0ZWQsIHNsb3QgPSAiZGF0YSIsIGFzc2F5ID0gIlJOQSIpKQoKIyMgcmVtb3ZlIGZlYXR1cmVzIHdpdGggZHVwbGljYXRlZCBuYW1lcwpzY2UgPC0gc2NlWyFkdXBsaWNhdGVkKHJvd25hbWVzKHNjZSkpLCBdCgojIyBidWlsZCBzY21hcC1jZWxsIHJlZmVyZW5jZSBpbmRleCwgc2F2ZSB0aGlzIHJkcwpzY2UgPC0gc2VsZWN0RmVhdHVyZXMoc2NlLCBzdXBwcmVzc19wbG90ID0gRkFMU0UsIG5fZmVhdHVyZXMgPSAyMDAwKQp0YWJsZShyb3dEYXRhKHNjZSkkc2NtYXBfZmVhdHVyZXMpCnNldC5zZWVkKDEpCnNjZSA8LSBpbmRleENlbGwoc2NlLCBNID0gNTAsIGsgPSA4MCkKbmFtZXMobWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4KQojbGVuZ3RoKG1ldGFkYXRhKHNjZSkkc2NtYXBfY2VsbF9pbmRleCRzdWJjZW50cm9pZHMpCiNkaW0obWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkc1tbMV1dKQojbWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNlbnRyb2lkc1tbMV1dWywxOjVdCiNkaW0obWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4JHN1YmNsdXN0ZXJzKQoKI3NhdmVSRFMocGJfZmlsdGVyZWRfc2NlX29ydGgsIGZpbGU9InBiX2ZpbHRlcmVkX3NjZV9vcnRoaW5kZXhfMjAxODExMDkucmRzIikKYGBgCgojIyMgTWFwIHRvIHRoZSBpbmRleAoKYGBge3J9CiNyb3dEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRmZWF0dXJlX3N5bWJvbCA8LSByb3dEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRvcnRoX25hbWUKI3Jvd25hbWVzKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSA8LSByb3dEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRvcnRoX25hbWUKCiNwcmVwIHRoZSBTQ0UsIGlmIHdhcyBvcmlnaW5hbGx5IGEgU3VlcmF0IG9iamVjdCBuZWVkIHRoZSBkZnMgdG8gYmUgcmVndWxhciBtYXRyaWNlcwojcGJfZmlsdGVyZWRfc2NlX29ydGggPC0gcGJfZmlsdGVyZWRfc2NlX29ydGhbLCBjb2xEYXRhKHBiX2ZpbHRlcmVkX3NjZV9vcnRoKSRhYnNjbHVzdDMgIT0gIjgiXQojc2NlIDwtIHBiX2ZpbHRlcmVkX3NjZV9vcnRoCiNwY2EgPC0gcGxvdFBDQShzY2UpCiNwY3MgPC0gcGNhJGRhdGEKI3RhYmxlKHJvd25hbWVzKHBjcyk9PWNvbG5hbWVzKHNjZSkpCgojY29sRGF0YShzY2UpIDwtIGNiaW5kKGNvbERhdGEoc2NlKSwgcGNzKQoKbXV0YW50c19jb3VudHMgPSBhcy5tYXRyaXgoR2V0QXNzYXlEYXRhKG11dGFudF9zZXVyYXQsIHNsb3QgPSAiY291bnRzIiwgYXNzYXkgPSAiUk5BIikpCm11dGFudHNfcGhlbm8gPSBhcy5kYXRhLmZyYW1lKG11dGFudF9zZXVyYXRAbWV0YS5kYXRhKQoKI3Jvd0RhdGEoc2NlKSRmZWF0dXJlX3N5bWJvbCA8LSByb3dEYXRhKHNjZSkkZ2VuZQptdXRhbnRzLnNjZSA8LSBTaW5nbGVDZWxsRXhwZXJpbWVudChsaXN0KGNvdW50cz1tdXRhbnRzX2NvdW50cyksCiAgICBjb2xEYXRhPURhdGFGcmFtZShsYWJlbD1tdXRhbnRzX3BoZW5vKSwKICAgIHJvd0RhdGE9RGF0YUZyYW1lKGZlYXR1cmVfc3ltYm9sPXJvd25hbWVzKG11dGFudHNfY291bnRzKSkpCm11dGFudHMuc2NlCgojIyBhZGQgbG9nIGNvdW50cwojIyBtYW51YWwKI2NvdW50c18xIDwtIGFzc2F5KG11dGFudHMuc2NlLCAiY291bnRzIikKI2xpYnNpemVzIDwtIGNvbFN1bXMoY291bnRzXzEpCiNzaXplLmZhY3RvcnMgPC0gbGlic2l6ZXMvbWVhbihsaWJzaXplcykKI2xvZ2NvdW50cyhtdXRhbnRzLnNjZSkgPC0gbG9nMih0KHQoY291bnRzXzEpL3NpemUuZmFjdG9ycykgKyAxKQojIyBmcm9tIHNldXJhdApsb2djb3VudHMobXV0YW50cy5zY2UpIDwtIGFzLm1hdHJpeChHZXRBc3NheURhdGEobXV0YW50X3NldXJhdCwgc2xvdCA9ICJkYXRhIiwgYXNzYXkgPSAiUk5BIikpCgojUHJvamVjdCBxdWVyeSBkYXRhIHNldCBvbnRvIGNlbGwgaW5kZXgKc2NtYXBDZWxsX3Jlc3VsdHMgPC0gc2NtYXBDZWxsKAogIG11dGFudHMuc2NlLCAKICBsaXN0KHd0ID0gbWV0YWRhdGEoc2NlKSRzY21hcF9jZWxsX2luZGV4CiAgKQopCgojI0xvb2sgaW50byB0aGUgcmVzdWx0cwojIEZvciBlYWNoIGRhdGFzZXQgdGhlcmUgYXJlIHR3byBtYXRyaWNpZXMuIGNlbGxzIG1hdHJpeCBjb250YWlucyB0aGUgdG9wIDEwIChzY21hcCBkZWZhdWx0KSBjZWxsIElEcyBvZiB0aGUgY2VsbHMgb2YgdGhlIHJlZmVyZW5jZSBkYXRhc2V0IHRoYXQgYSBnaXZlbiBjZWxsIG9mIHRoZSBwcm9qZWN0aW9uIGRhdGFzZXQgaXMgY2xvc2VzdCB0bzoKIyAgIAojICAgR2l2ZSBhc3NpZ25tZW50cyBpbiB0d28gd2F5czoKIyAgIDEuIFRha2UgdGhlIHRvcCBjZWxsIGFzc2lnbm1lbnQgYWJzIGNsdXN0LCBpZiBjb3NpbmUgc2ltaWxhcml0eSBpcyBsZXNzIHRoYW4gMC40IChvciBhZGp1c3QgaWYgbmVlZGVkKSBtYXJrIGFzIHVuYXNzaWduZWQKIyAyLiBGb3IgdGhlIHRvcCAzIG5lYXJlc3QgbmVpZ2hib3JzLCBnZXQgYSBtZWFuIG9mIHRoZSBQQ0EgY29vcmRpbmF0ZXMgYW5kIHNuYXAgdG8gdGhlIG5lYXJlc3QgY2VsbCBvZiB0aG9zZSBjb29yZGluYXRlcy4gSWYgYW55IG9mIHRoZSB0b3AgdGhyZWUgY2VsbHMgYXJlIHNpbSBiZWxvdyAwLjQgdGhlbiBtYXJrIGFzIHVuYXNzaWduZWQuCgoKIyNUb3AgY2VsbCBhc3NpZ25tZW50IG1ldGhvZAoKIyMgbG9vayBhdCBhc3NpZ25tZW50cwpzY21hcENlbGxfcmVzdWx0cyR3dCRjZWxsc1ssIDE6M10KIyMgZ2V0IGNlbGwgaW5kZXhlcyAKZ2V0Y2VsbHMgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3QkY2VsbHNbMSwgXQojIyBleGN0cmFjdCBjZWxscyBtZXRhZGF0YSBmcm9tIGluZGV4CmNkc2NlIDwtIGNvbERhdGEoc2NlKVtnZXRjZWxscywgXQojIyBleHRyYWN0IHNpbWlsYXJpdGllcwp0b3BzaW0gPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3Qkc2ltaWxhcml0aWVzWzEsIF0KIyMgZ2V0IG5hbWUgb2YgdG9wIGNlbGwgbWF0Y2hlZAptdXRhbnRzLnNjZSR0b3BjZWxsIDwtIHJvd25hbWVzKGNkc2NlKQojIyBnZXQgc2V4IGlkCm11dGFudHMuc2NlJHRvcGNlbGxfYWMgPC0gY2RzY2UkbGFiZWwubW9ub2NsZV9zZXgKIyMgZ2V0IGNvb3JkaW5hdGVzIG9mIG1hdGNoZWQgY2VsbAptdXRhbnRzLnNjZSRpbmRleFBDMSA8LSBjZHNjZSRsYWJlbC5VTUFQXzEKbXV0YW50cy5zY2UkaW5kZXhQQzIgPC0gY2RzY2UkbGFiZWwuVU1BUF8yCiNtdXRhbnRzLnNjZSRwYnB0IDwtIGNkc2NlJHBzZXVkb3RpbWUKI211dGFudHMuc2NlJHBiYnVsayA8LSBjZHNjZSRidWxrCm11dGFudHMuc2NlJHRvcGNlbGxfc3AgPC0gbXV0YW50cy5zY2UkdG9wY2VsbF9hYwptdXRhbnRzLnNjZSR0b3BzaW0gPC0gdG9wc2ltCm11dGFudHMuc2NlJHRvcGNlbGxfc3BbbXV0YW50cy5zY2UkdG9wc2ltIDwgMC40XSA8LSAidW5hc3NpZ25lZCIKdGFibGUobXV0YW50cy5zY2UkdG9wY2VsbF9zcCkKYGBgCgpgYGB7cn0KIyMgc2VlIGhvdyB0aGlzIG92ZXJsYXBzIHdpdGggZmx1b3Jlc2NlbmNlIHNvcnRlZCBvbiBmb3IgODIwIHRvIGNvbmZpcm0gYWNjdXJhY3kKZGZfODIwIDwtIGNvbERhdGEobXV0YW50cy5zY2UpW2NvbERhdGEobXV0YW50cy5zY2UpJGxhYmVsLmdlbmV0aWNfYmFja2dyb3VuZCA9PSJQQkFOS0FfODIwIiwgXQp0YWJsZShkZl84MjAkdG9wY2VsbF9zcCwgZGZfODIwJGxhYmVsLmZsdW9yZXNlbmNlX3NvcnRlZF9vbikKYGBgCgpgYGB7cn0KdGFibGUoY29sRGF0YShtdXRhbnRzLnNjZSkkdG9wY2VsbF9zcCwgY29sRGF0YShtdXRhbnRzLnNjZSkkbGFiZWwuaWRlbnRpdHlfbmFtZV91cGRhdGVkKQpgYGAKCgpgYGB7cn0KIyMjIyBUT1AgM05OIG1ldGhvZAoKI1RoaXMgZnVuY3Rpb24gbWFrZXMgYSBsaXN0IG9mIHRoZSBQQyBtZWFucyBmb3IgZWFjaCBjZWxsIGFuZCB0aGVuIGRvLmNhbGwgYmVsb3cgcmJpbmRzIHRoZW0gaW50byBhIGRhdGFmcmFtZSBjYWxsZWQgYmlnX2RhdGEKCmRhdGFsaXN0ID0gbGlzdCgpCgpmb3IgKGkgaW4gY29sbmFtZXMoc2NtYXBDZWxsX3Jlc3VsdHMkd3QkY2VsbHMpKSB7CiAgCiAgZ2V0Y2VsbHN0ZXN0IDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JGNlbGxzWzE6MywgaV0KICBjZHNjZXRlc3QgPC0gY29sRGF0YShzY2UpW2dldGNlbGxzdGVzdCwgXQogIFBDMW1lYW4gPC0gbWVhbihjZHNjZXRlc3QkbGFiZWwuVU1BUF8xKQogIFBDMm1lYW4gPC0gbWVhbihjZHNjZXRlc3QkbGFiZWwuVU1BUF8yKQogICMgLi4uIG1ha2Ugc29tZSBkYXRhCiAgZGF0IDwtIGRhdGEuZnJhbWUoaSwgUEMxbWVhbiwgUEMybWVhbikKICBkYXQkaSA8LSBpICAjIG1heWJlIHlvdSB3YW50IHRvIGtlZXAgdHJhY2sgb2Ygd2hpY2ggaXRlcmF0aW9uIHByb2R1Y2VkIGl0PwogIGRhdGFsaXN0W1tpXV0gPC0gZGF0ICMgYWRkIGl0IHRvIHlvdXIgbGlzdAp9CgpiaWdfZGF0YSA9IGRvLmNhbGwocmJpbmQsIGRhdGFsaXN0KQojIG9yIGJpZ19kYXRhIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZGF0YWxpc3QpCiMgb3IgYmlnX2RhdGEgPC0gZGF0YS50YWJsZTo6cmJpbmRsaXN0KGRhdGFsaXN0KQoKdGVzdCA8LSBiaWdfZGF0YVsxLCBdCgpkZiA8LSBkYXRhLmZyYW1lKFg9Y29sRGF0YShzY2UpJGxhYmVsLlVNQVBfMSwgWT1jb2xEYXRhKHNjZSkkbGFiZWwuVU1BUF8yLCByb3cubmFtZXMgPSByb3duYW1lcyhjb2xEYXRhKHNjZSkpKQoKI3RoZSBzbmFwIGZ1bmN0aW9uIHNuYXBzIHRvIHRoZSBuZWFyZXN0IGNlbGwgaW4gUEMgY29vcmRpYW50ZXMKc25hcCA8LSBmdW5jdGlvbihkZiwgdGVzdCl7CiAgcmVxdWlyZShCaW9iYXNlKQogIGQgPC0gbWF0Y2hwdChhcy5tYXRyaXgoZGYpLAogICAgICAgICAgICAgICBhcy5tYXRyaXgoZGF0YS5mcmFtZShYPXRlc3QkUEMxbWVhbixZPXRlc3QkUEMybWVhbikpKQogIAogIG1pbl9yb3cgPC0gcm93bmFtZXMoZFtkJGRpc3RhbmNlPT1taW4oZCRkaXN0YW5jZSksXSkKICAKICB0ZXN0JFhfc25hcCA8LSB1bmlxdWUoZGZbbWluX3JvdywiWCJdKQogIHRlc3QkWV9zbmFwIDwtIHVuaXF1ZShkZlttaW5fcm93LCJZIl0pCiAgdGVzdCRwYl9jZWxsIDwtIG1pbl9yb3cKICAKICB0ZXN0Cn0KCiN0aGlzIGxvb3BzIHRocm91Z2ggZWFjaCBjZWxsIGFuZCBpbiBiaWdfZGF0YSBhbmQgcnVucyB0aGUgc25hcCBmdW5jdGlvbgpkYXRhbGlzdDIgPSBsaXN0KCkKY29sbmFtZXMoYmlnX2RhdGEpIDwtIGMoInNhbXBsZV9pZCIsICJQQzFtZWFuIiwgIlBDMm1lYW4iKQpmb3IgKGkgaW4gcm93bmFtZXMoYmlnX2RhdGEpKSB7CiAgdGVzdCA8LSBiaWdfZGF0YVtpLCBdCiAgY29vcmQgPC0gc25hcChkZiwgdGVzdCkKICBjb29yZCRpIDwtIGkKICBkYXRhbGlzdDJbW2ldXSA8LSBjb29yZAp9CmJpZ19kYXRhMiA9IGRvLmNhbGwocmJpbmQsIGRhdGFsaXN0MikKCgp0YWJsZShyb3duYW1lcyhiaWdfZGF0YTIpPT1yb3duYW1lcyhjb2xEYXRhKG11dGFudHMuc2NlKSkpCgphbGxwYmNkIDwtIGNvbERhdGEoc2NlKQphbGxwYmNkIDwtIGFzLmRhdGEuZnJhbWUoYWxscGJjZCkKcGJhYnNjbHVzdCA8LSBhbGxwYmNkWywgYygibGFiZWwucHRfaWRfY29scyIsICJsYWJlbC5pZGVudGl0eV9uYW1lX3VwZGF0ZWQiLCAibGFiZWwubW9ub2NsZV9zZXgiKSwgZHJvcD1GQUxTRV0KcGJhYnNjbHVzdCRwYl9zYW1wbGVfaWQgPC0gcm93bmFtZXMocGJhYnNjbHVzdCkKCiMgTm93IG1lcmdlIHRoZSBwYyBjZWxsIGFzaWdubWVudHMgd2l0aCB0aGVpciBhYnMgY2x1c3QgYW5kIGdldCBpbiB0aGUgcmlnaHQgb3JkZXIKYmlnX2RhdGEzIDwtIG1lcmdlKGJpZ19kYXRhMiwgcGJhYnNjbHVzdCwgYnkueCA9ICJwYl9jZWxsIiwgYnkueSA9ICJwYl9zYW1wbGVfaWQiLCBhbGwueD1UUlVFLCBhbGwueT1GQUxTRSkKYmlnX2RhdGE0IDwtIGJpZ19kYXRhM1ttYXRjaChyb3duYW1lcyhiaWdfZGF0YTIpLCBiaWdfZGF0YTMkc2FtcGxlX2lkKSwgXQoKCmNvbG9ycyA8LSBjKCI2Ij0iIzc4QzY3OSIsCiAgICAgICAgICAgICIyIj0iI0QxRUM5RiIsCiAgICAgICAgICAgICIwIj0iI0ZFQjI0QyIsCiAgICAgICAgICAgICIxIj0iI0Y0Q0Y2MyIsCiAgICAgICAgICAgICIzIj0iI0ZFRUVBQSIsCiAgICAgICAgICAgICI0Ij0iIzg1QjFEMyIsCiAgICAgICAgICAgICI3Ij0iIzllY2FlMSIsCiAgICAgICAgICAgICI1Ij0iI0M5RThGMSIsCiAgICAgICAgICAgICJNIj0gIiNCN0I3RDgiLAogICAgICAgICAgICAiRiI9IiM5Qzk2QzYiLAogICAgICAgICAgICAidW5hc3NpZ25lZCI9ImJsYWNrIikKCmdncGxvdChiaWdfZGF0YTQsIGFlcyhQQzFtZWFuLCBQQzJtZWFuKSkgKwogIGdlb21fcG9pbnQoY29sID0gYmlnX2RhdGE0JGxhYmVsLnB0X2lkX2NvbHMpICsKICAgICAgICAgICAgICAgICAgICAgdGhlbWVfdm9pZCgpICsKICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKQoKIysgZ2VvbV9wb2ludChhZXMoY29sb3VyPWZhY3RvcihiaWdfZGF0YTQkbGFiZWwubGFiZWwucHRfaWRfY29scykpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpIAoKICAgICAgICAgICAgICAgICAgICAgCgpnZ3Bsb3QoYmlnX2RhdGE0LCBhZXMoWF9zbmFwLCBZX3NuYXApKSArCiAgZ2VvbV9wb2ludChjb2wgPSBiaWdfZGF0YTQkbGFiZWwucHRfaWRfY29scykgKwogICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKwogICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpIAoKIysgZ2VvbV9wb2ludChhZXMoY29sb3VyPWZhY3RvcihiaWdfZGF0YTQkbGFiZWwubGFiZWwucHRfaWRfY29scykpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpIAoKIyNhZGQgaW5mbyB0byBTQ0UgYW5kIHNhdmUgY29sRGF0YSwgdG8gYmUgYW4gYXNzaWduZWQgY2VsbCBhbGwgM05OIG11c3QgaGF2ZSBhIGNvcyBzaW0gPjAuNApzY21hcENlbGxfcmVzdWx0cyR3dCRzaW1pbGFyaXRpZXNbLCAxOjNdCnRvcHNpbTEgPC0gc2NtYXBDZWxsX3Jlc3VsdHMkd3Qkc2ltaWxhcml0aWVzWzEsIF0KdG9wc2ltMiA8LSBzY21hcENlbGxfcmVzdWx0cyR3dCRzaW1pbGFyaXRpZXNbMiwgXQp0b3BzaW0zIDwtIHNjbWFwQ2VsbF9yZXN1bHRzJHd0JHNpbWlsYXJpdGllc1szLCBdCgp0YWJsZShiaWdfZGF0YTQkc2FtcGxlX2lkPT1yb3duYW1lcyhjb2xEYXRhKG11dGFudHMuc2NlKSkpCiNwZm9iaiRwYl9jZWxsIDwtIGJpZ19kYXRhNCRwYl9jZWxsCiNwZm9iaiRQQzFtZWFuIDwtIGJpZ19kYXRhNCRQQzFtZWFuCmJkNCA8LSBiaWdfZGF0YTRbLCBjKCJwYl9jZWxsIiwgInNhbXBsZV9pZCIsICJQQzFtZWFuIiwgIlBDMm1lYW4iLCAiWF9zbmFwIiwgIllfc25hcCIsICJsYWJlbC5wdF9pZF9jb2xzIiwgImxhYmVsLmlkZW50aXR5X25hbWVfdXBkYXRlZCIsICJsYWJlbC5tb25vY2xlX3NleCIpXQoKY29sRGF0YShtdXRhbnRzLnNjZSkgPC0gY2JpbmQoY29sRGF0YShtdXRhbnRzLnNjZSksIGJkNCkKCm11dGFudHMuc2NlJHRvcHNpbTEgPC0gdG9wc2ltMQptdXRhbnRzLnNjZSR0b3BzaW0yIDwtIHRvcHNpbTIKbXV0YW50cy5zY2UkdG9wc2ltMyA8LSB0b3BzaW0zCm11dGFudHMuc2NlJHN0YWdlX3ByZWQgPC0gYmlnX2RhdGE0JGxhYmVsLm1vbm9jbGVfc2V4Cm11dGFudHMuc2NlJHN0YWdlX3ByZWRbbXV0YW50cy5zY2UkdG9wc2ltMSA8IDAuNCB8IG11dGFudHMuc2NlJHRvcHNpbTIgPCAwLjQgfCBtdXRhbnRzLnNjZSR0b3BzaW0zIDwgMC40XSA8LSAidW5hc3NpZ25lZCIKdGFibGUobXV0YW50cy5zY2Ukc3RhZ2VfcHJlZCkKCiN3cml0ZS5jc3YoYmQ0LCAicGZjZWxsYXNzaWdubWVudHN3aXRobWVhbjNubl8yMDE4MTAyOS5jc3YiKQojd3JpdGUuY3N2KGNvbERhdGEocGZvYmopLCAicGYzZDcxMDBzY21hcGNsdXN0czJtZXRob2RpbmRleG4xMDBfMjAxOTAxMDcuY3N2IikKYGBgCgpgYGB7cn0KIyMgc2VlIGhvdyB0aGlzIG92ZXJsYXBzIHdpdGggZmx1b3Jlc2NlbmNlIHNvcnRlZCBvbiBmb3IgODIwIHRvIGNvbmZpcm0gYWNjdXJhY3kKZGZfODIwIDwtIGNvbERhdGEobXV0YW50cy5zY2UpW2NvbERhdGEobXV0YW50cy5zY2UpJGxhYmVsLmdlbmV0aWNfYmFja2dyb3VuZCA9PSJQQkFOS0FfODIwIiwgXQp0YWJsZShkZl84MjAkc3RhZ2VfcHJlZCwgZGZfODIwJGxhYmVsLmZsdW9yZXNlbmNlX3NvcnRlZF9vbikKYGBgCgpgYGB7cn0KdGFibGUoY29sRGF0YShtdXRhbnRzLnNjZSkkc3RhZ2VfcHJlZCwgY29sRGF0YShtdXRhbnRzLnNjZSkkbGFiZWwuaWRlbnRpdHlfbmFtZV91cGRhdGVkKQpgYGAKCgojIyBtYWtlIGZpbmFsIHBsb3Qgd2l0aCBNQ0EgZGF0YSBiZWxvdwpgYGB7cn0KIyMgUmVhZCBpbiBNQ0EgZGF0YQpwaGVubyA8LSByZWFkLmNzdigiLi4vc2NtYXAvYWxscGIxMHhfcGhlbm8uY3N2IikKIyMgZXh0cmFjdCByb3dzIG5lZWRlZCBmb3IgcGxvdHRpbmcKZGZfcGxvdCA8LSBwaGVub1ssYygiUEMyXzNkIiwgIlBDM18zZCIsICJhYnNjbHVzdDMiKV0KZGZfcGxvdCRleHBlcmltZW50IDwtIGRmX3Bsb3QkYWJzY2x1c3QzCgojIyBleHRyYWN0IHJvd3MgbmVlZGVkIGZvciBwbG90dGluZyBmcm9tIG1hcHBlZCBvYmplY3QKZGZfcGxvdF9wbSA8LSBhcy5kYXRhLmZyYW1lKGNvbERhdGEocG1fc3MyX2ZpZWxkLnNjZS5vcnRoKSkKZGZfcGxvdF9wbSA8LSBkZl9wbG90X3BtWyAsYygiWF9zbmFwIiwgIllfc25hcCIsICJsYWJlbC5hYnNjbHVzdDMiKV0KZGZfcGxvdF9wbSRleHBlcmltZW50IDwtICJwbSIKY29sbmFtZXMoZGZfcGxvdF9wbSkgPC0gYygiUEMyXzNkIiwgIlBDM18zZCIsICJhYnNjbHVzdDMiLCAiZXhwZXJpbWVudCIpCgojIyBleHRyYWN0IHJvd3MgbmVlZGVkIGZvciBwbG90dGluZyBmcm9tIG1hcHBlZCBvYmplY3QKZGZfcGxvdF9wZiA8LSBhcy5kYXRhLmZyYW1lKGNvbERhdGEocGZfc3MyX2ZpZWxkLnNjZS5vcnRoKSkKZGZfcGxvdF9wZiA8LSBkZl9wbG90X3BmWyAsYygiWF9zbmFwIiwgIllfc25hcCIsICJsYWJlbC5hYnNjbHVzdDMiKV0KZGZfcGxvdF9wZiRleHBlcmltZW50IDwtICJwZiIKY29sbmFtZXMoZGZfcGxvdF9wZikgPC0gYygiUEMyXzNkIiwgIlBDM18zZCIsICJhYnNjbHVzdDMiLCAiZXhwZXJpbWVudCIpCgojIyBiaW5kIHRvZ2V0aGVyCmRmX3Bsb3QgPC0gcmJpbmQoZGZfcGxvdCwgZGZfcGxvdF9wZiwgZGZfcGxvdF9wbSkKCmNvbG9ycyA8LSBjKCI2Ij0iIzc4QzY3OSIsCiAgICAgICAgICAgICIyIj0iI0QxRUM5RiIsCiAgICAgICAgICAgICIwIj0iI0ZFQjI0QyIsCiAgICAgICAgICAgICIxIj0iI0Y0Q0Y2MyIsCiAgICAgICAgICAgICIzIj0iI0ZFRUVBQSIsCiAgICAgICAgICAgICI0Ij0iIzg1QjFEMyIsCiAgICAgICAgICAgICI3Ij0iIzllY2FlMSIsCiAgICAgICAgICAgICI1Ij0iI0M5RThGMSIsCiAgICAgICAgICAgICJNIj0gIiNCN0I3RDgiLAogICAgICAgICAgICAiRiI9IiM5Qzk2QzYiLAogICAgICAgICAgICAidW5hc3NpZ25lZCI9ImJsYWNrIiwKICAgICAgICAgICAgInBtIiA9ICIjZGM2NWE0IiwKICAgICAgICAgICAgInBmIiA9ICIjMjQyNDVmIikKCiMjIGFkZCBhbHBoYSBmb3IgcGxvdHRpbmcKZGZfcGxvdCRhbHBoYVshZGZfcGxvdCRleHBlcmltZW50ID09ICJwbSJdIDwtIDAuNQpkZl9wbG90JGFscGhhW2RmX3Bsb3QkZXhwZXJpbWVudCA9PSAicG0iXSA8LSAxCmRmX3Bsb3QkYWxwaGFbZGZfcGxvdCRleHBlcmltZW50ID09ICJwZiJdIDwtIDEKCiMjcGxvdApzY21hcF9wY2EgPC0gZ2dwbG90KGRmX3Bsb3QsIGFlcyh4PVBDMl8zZCwgeSA9IFBDM18zZCxjb2xvdXI9ZXhwZXJpbWVudCwgYWxwaGEgPSBhbHBoYSkpICsgCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZV92b2lkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpICsKICAjIyByZW1vdmUgYWxwaGEgc2NhbGUKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKGd1aWRlPUZBTFNFKQogICMjIGRyYXcgcmluZyBhcm91bmQgZmllbGQgc2FtcGxlcwogICNnZW9tX3BvaW50KGRhdGE9ZGZfcGxvdFtkZl9wbG90JGV4cGVyaW1lbnQgPT0gInBtIiwgXSwgcGNoPTIxLCBmaWxsPU5BLCBzaXplPTIsIGNvbG91cj0iYmxhY2siLCBzdHJva2U9MSkgKwogICMjIG1ha2Ugbm9uLWZpZWxkIHNhbXBsZXMgbW9yZSBvcGFxdWUKICAjZ2VvbV9wb2ludChkYXRhPWRmX3Bsb3RbLWRmX3Bsb3QkZXhwZXJpbWVudCA9PSAicG0iLCBdLCBhbHBoYSA9IDAuMikKCiMjIHZpZXcKc2NtYXBfcGNhXzIgPC0gc2NtYXBfcGNhICsgCiAgZ3VpZGVzKGNvbG91cj1ndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTQpKSkKCnNjbWFwX3BjYV8yCmBgYAoKc2F2ZQpgYGB7cn0KI2dnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9maWVsZF9zYW1wbGVzX3NjbWFwLnBuZyIsIHBsb3QgPSBzY21hcF9wY2FfMiwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMTUsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCwgbGltaXRzaXplID0gVFJVRSkKYGBgCgojIyBPdmVybGFwIGFuZCB2YWxpZGF0aW9uCgpgYGB7cn0KCmBgYAoKYGBge3J9CgpgYGAKCiMgMTEuIFNhdmUgYW5kIEV4cG9ydCB7LnRhYnNldH0KCiMjIHNhdmUKClNhdmUgZW52aXJvbm1lbnQKYGBge3J9CiMjIFRoaXMgc2F2ZXMgZXZlcnl0aGluZyBpbiB0aGUgZ2xvYmFsIGVudmlyb25tZW50IGZvciBlYXN5IHJlY2FsbCBsYXRlcgojc2F2ZS5pbWFnZShmaWxlID0gIkdDU0tPX21lcmdlLlJEYXRhIikKI2xvYWQoZmlsZSA9ICJHQ1NLT19tZXJnZS5SRGF0YSIpCmBgYAoKU2F2ZSBvYmplY3QocykKYGBge3J9CiMjIFNhdmUgYW4gb2JqZWN0IHRvIGEgZmlsZQpzYXZlUkRTKHRlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L3RlbnguanVzdHd0LmludGVncmF0ZWQuc2V4LlJEUyIpCiMjIFJlc3RvcmUgdGhlIG9iamVjdAojcmVhZFJEUyhmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L3RlbngubXV0YW50LmludGVncmF0ZWQuc2V4LlJEUyIpCgojIyBzYXZlIGludGVncmF0ZWQgb2JqZWN0IHRvIGZpbGUKc2F2ZVJEUyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L3RlbnguanVzdHd0LmludGVncmF0ZWQuUkRTIikgCiMjIHJlc3RvcmUgdGhlIG9iamVjdAojdGVueC5qdXN0d3QuaW50ZWdyYXRlZCA8LSByZWFkUkRTKCIuLi9kYXRhX3RvX2V4cG9ydC90ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLlJEUyIpCgojIyBzYXZlIG1vbm9jbGUgb2JqZWN0CnNhdmVSRFMobW9ub2NsZS5vYmplY3QuYWxsLCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L21vbm9jbGUub2JqZWN0LmFsbC5SRFMiKSAKIyMgcmVzdG9yZSB0aGUgb2JqZWN0CiNtb25vY2xlLm9iamVjdC5hbGwgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvbW9ub2NsZS5vYmplY3QuYWxsLlJEUyIpCgojIyBzYXZlIGludGVncmF0ZWQgb2JqZWN0IHRvIGZpbGUKI3NhdmVSRFMoR0NTS09fbXV0YW50cywgZmlsZSA9ICIuLi9kYXRhX3RvX2V4cG9ydC9HQ1NLT19tdXRhbnRzLlJEUyIpIAojIyByZXN0b3JlIHRoZSBvYmplY3QKI3RlbnguanVzdHd0LmludGVncmF0ZWQgPC0gcmVhZFJEUygiLi4vZGF0YV90b19leHBvcnQvdGVueC5qdXN0d3QuaW50ZWdyYXRlZC5SRFMiKQoKIyMgZXh0cmFjdCBVTUFQIGNvb3JkaW5hdGVzIGFuZCBtZXRhZGF0YQojIyBleHRyYWN0IG1ldGFkYXRhCm1jYV93ZWJzaXRlX2RmIDwtIHRlbnguanVzdHd0LmludGVncmF0ZWRAbWV0YS5kYXRhCgojIyBhZGQgdW1hcCAtIG1lcmdlIG9uIHJvdyBuYW1lcyBhbmQgdGhlbiBtYWtlIHN1cmUgcm93IG5hbWVzIGFyZSBub3QgZHJvcHBlZCBvciBhZGRlZAptY2Ffd2Vic2l0ZV9kZiA8LSB0cmFuc2Zvcm0obWVyZ2UobWNhX3dlYnNpdGVfZGYsIHRlbnguanVzdHd0LmludGVncmF0ZWRAcmVkdWN0aW9uc1tbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzLCBieT0wLCBhbGw9VFJVRSksIHJvdy5uYW1lcz1Sb3cubmFtZXMsIFJvdy5uYW1lcz1OVUxMKQoKIyMgc2VuZCB0aGlzIHRvIHN1bmlsOgojIGdncGxvdChtY2Ffd2Vic2l0ZV9kZiwgYWVzKHggPSBVTUFQXzEsIHkgPSBVTUFQXzIpKSArCiMgZ2VvbV9wb2ludChjb2wgPSBtY2Ffd2Vic2l0ZV9kZiRwdF9pZF9jb2xzKSArCiMgdGhlbWVfdm9pZCgpICsKIyBjb29yZF9maXhlZCgpCgojIyBleHBvcnQKd3JpdGUuY3N2KG1jYV93ZWJzaXRlX2RmLCBmaWxlID0gIi4uL2RhdGFfdG9fZXhwb3J0L21jYV93ZWJzaXRlX2RmLmNzdiIpCmBgYAoKQ2xlYW4gdXAKYGBge3J9CiNybShzczJfd3RfY2VsbHMpCiNybSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkKQojcm0odGVueC5qdXN0d3QubGlzdCkKYGBgCgojIyBmaW5hbCBmaWd1cmUgY29uc3RydWN0aW9uCgpbQ293cGxvdF0oaHR0cHM6Ly93aWxrZWxhYi5vcmcvY293cGxvdC9hcnRpY2xlcy9wbG90X2dyaWQuaHRtbCkocGxvdF9ncmlkKSwgW3BhdGNod29ya10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BhdGNod29yay92aWduZXR0ZXMvcGF0Y2h3b3JrLmh0bWwpKHdyYXBfcGxvdHMpLCBhbmQgW2dncHVicl0oaHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC9hcnRpY2xlcy8yNC1nZ3B1YnItcHVibGljYXRpb24tcmVhZHktcGxvdHMvODEtZ2dwbG90Mi1lYXN5LXdheS10by1taXgtbXVsdGlwbGUtZ3JhcGhzLW9uLXRoZS1zYW1lLXBhZ2UvKSBjYW4gYWxsIGFsbG93IG11bHRpcGxlIHBsb3RzIHRvIGJlIHBsb3R0ZWQgdG9nZXRoZXIuIAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMS43LCBmaWcud2lkdGggPSA4LjN9CiMjIEEKIyB1bWFwX2lkX3B0CiMjIEIKIyBtYXJrZXIgZ2VuZSBleHByZXNzaW9uCiMjIEMKIyBNdXRhbnQgZ2VuZSBleHByZXNzaW9uCiMjIEQKIyBNb2R1bGVzCgojRmlndXJlX0EgPC0gZ3JpZC5hcnJhbmdlKGFycmFuZ2VHcm9iKFFDX2NvbXBvc2l0ZV9wbG90LCBRQ19taXRvX3Zpb2xpbiwgUUNfbWl0b19ncmFwaCwgUUNfYnlfZ2Vub3R5cGUsIG1hcHBpbmdfcmF0ZV9wbG90KSwgbnJvdz0zKSwgbnJvdz0yLCBoZWlnaHRzPWMoMTAsMikpCgojIyBjb3dwbG90IG1ldGhvZAojIyBjYW4gdXNlIHRoaXMgZm9yIGxhYmVsczogdG91cHBlcihsZXR0ZXJzKVsxOjEwXQoKIyMgQy4gTXV0YW50IGdlbmVzCm11dGFudF9nZW5lc19maWd1cmUgPC0gcGxvdF9ncmlkKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIyBtYXJrZXIgZ2VuZXMgc3RhcnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfRkFNQiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9NU1A4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X01TUDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9DQ1AyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X01HMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMgbXV0YW50IGdlbmVzIHN0YXJ0cyAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfZ2QxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9tZDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfbWQzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X21kNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfbWQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2ZkMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyX2dlbmVfcGxvdF9mZDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcl9nZW5lX3Bsb3RfZmQzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJfZ2VuZV9wbG90X2ZkNCwgCiAgbGFiZWxfc2l6ZSA9IDEsIAogIG5yb3cgPSA0KQoKIyMgbGFiZWxzIGFzIHVwcGVyY2FzZSBsZXR0ZXJzOgojYyh0b3VwcGVyKGxldHRlcnMpWzI6MTddKQojIGxhYmVscyBhcyByb21hbiBudW1lcmFsczoKIyBjKHRvbG93ZXIoYXMucm9tYW4oYygyOjE3KSkKCkZpZ3VyZV9wdWJsaWNhdGlvbiA8LSBwbG90X2dyaWQodW1hcF9pZF9wdCArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAsIDAsIDAsIDApLCAiY20iKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGFudF9nZW5lc19maWd1cmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMgYWRkIGVtcHR5IHBsb3QgdG8gZ2l2ZSBzcGFjaW5nCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyB0aGVtZV92b2lkKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygnQScsICdCJyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX3NpemUgPSAxMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDEsIDEsIDQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLCAyLCAzKSkKCkZpZ3VyZV9wdWJsaWNhdGlvbgpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9GaWd1cmVfQy5wbmciLCBwbG90ID0gRmlndXJlX3B1YmxpY2F0aW9uLCBkZXZpY2UgPSAicG5nIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSAyMSwgaGVpZ2h0ID0gMjkuNywgdW5pdHMgPSAiY20iLCBkcGkgPSAzMDAsIGxpbWl0c2l6ZSA9IFRSVUUpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMS43LCBmaWcud2lkdGggPSA4LjN9CmxheW91dCA8LSAiCkFBQUJCQgpDQ0RERUUKRkZHR0hICklJSkpLSwoiCgpGaWd1cmVfcHVibGljYXRpb25fQSA8LSAoY29tcG9zaXRpb25fdW1hcF8xMHggKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDEwKSkpICsKKGNvbXBvc2l0aW9uX3VtYXBfc3MyICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAxMCkpKSArIApwbG90X2xheW91dChuY29sID0gMikKCkZpZ3VyZV9wdWJsaWNhdGlvbiA8LSBGaWd1cmVfcHVibGljYXRpb25fQSArCiMoVU1BUF9ob28gKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDEwKSkgKyBsYWJzKHRpdGxlPSJQcmVkaWN0ZWQgQXNleHVhbCBDeWNsZSBSZWFsIFRpbWVwb2ludCIpKSArCiMoVU1BUF9rYXNpYSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMTApKSArIGxhYnModGl0bGU9IlByZWRpY3RlZCBHYW1ldG9jeXRvZ2VuZXNpcyBSZWFsIFRpbWVwb2ludCIpKSArCiAgIyMgbWFya2VyIGdlbmVzCm1hcmtlcl9nZW5lX3Bsb3RfRkFNQiArCm1hcmtlcl9nZW5lX3Bsb3RfTVNQOCArCm1hcmtlcl9nZW5lX3Bsb3RfTVNQMSArCm1hcmtlcl9nZW5lX3Bsb3RfQ0RQSzUgKwptYXJrZXJfZ2VuZV9wbG90X0FQMkcgKwptYXJrZXJfZ2VuZV9wbG90X0NDUDIgKwptYXJrZXJfZ2VuZV9wbG90X01HMSArCm1hcmtlcl9nZW5lX3Bsb3RfT1JDMSArCm1hcmtlcl9nZW5lX3Bsb3RfTUNNNCArCiAgIyMgbXV0YW50IGdlbmVzIHN0YXJ0cyAgCiNtYXJrZXJfZ2VuZV9wbG90X2dkMSArCiNtYXJrZXJfZ2VuZV9wbG90X21kMSArCiNtYXJrZXJfZ2VuZV9wbG90X21kMiArCiNtYXJrZXJfZ2VuZV9wbG90X21kMyArCiNtYXJrZXJfZ2VuZV9wbG90X21kNCArIAojbWFya2VyX2dlbmVfcGxvdF9tZDUgKwojbWFya2VyX2dlbmVfcGxvdF9mZDEgKwojbWFya2VyX2dlbmVfcGxvdF9mZDIgKwojbWFya2VyX2dlbmVfcGxvdF9mZDMgKwojbWFya2VyX2dlbmVfcGxvdF9mZDQgKyAKcGxvdF9sYXlvdXQobmNvbCA9IDYsIAogICAgICAgICAgICB3aWR0aHMgPSBjKDEsIDEsIDEsIDEsIDEgLDEpLAogICAgICAgICAgICBoZWlnaHRzID0gYygyLCAxLCAxLCAxKSwKICAgICAgICAgICAgZGVzaWduID0gbGF5b3V0CiAgICAgICAgICAgICkKCkZpZ3VyZV9wdWJsaWNhdGlvbgpgYGAKCnNhdmUKYGBge3J9Cmdnc2F2ZSgiLi4vaW1hZ2VzX3RvX2V4cG9ydC9GaWd1cmVfUzIucG5nIiwgcGxvdCA9IEZpZ3VyZV9wdWJsaWNhdGlvbiwgZGV2aWNlID0gInBuZyIsIHBhdGggPSBOVUxMLCBzY2FsZSA9IDEsIHdpZHRoID0gMjEsIGhlaWdodCA9IDI5LjcsIHVuaXRzID0gImNtIiwgZHBpID0gMzAwLCBsaW1pdHNpemUgPSBUUlVFKQpgYGAKCiMgQXBwZW5kaXggey50YWJzZXR9CgojIyBTZXNzaW9uIEluZm8gCmBgYHtyLCBlY2hvID0gRkFMU0V9CnNlc3Npb25JbmZvKCkKYGBgCgojIEV4cHJlc3Npb24gcGxvdHMKCiMjIyMgRXhwcmVzc2lvbiAtIHJhdyAtIFZpcmlkaXMKYGBge3IsIGZpZy5oZWlnaHQgPSAxNSwgZmlnLndpZHRoID0gMTV9CiMjIGZpbmQgYSBnb29kIHJpbmcgbWFya2VyLCB0byBzZWUgaWYgdGhlcmUgaXMgYSBiZXR0ZXIgb25lIHRoYW4gdGhlIG9uZXMgcmVwb3J0ZWQKI21hcmtlcnNfcmluZyA8LSBGaW5kTWFya2Vycyh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBpZGVudC4xID0gYygiNCIsICI1IiwgIjE2IiwgIjExIiwgIjciLCAiMyIsICI5IiwgIjAiLCAiMjIiKSkKI2hlYWQobWFya2Vyc19yaW5nKQoKIyBQQkFOS0EtMTMxOTUwMCAtIENDUDIgLSBmZW1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTA0MTYxMDAgLSBNRzEgLSBkeW5lbmluIGhlYXZ5IGNoYWluIC0gbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMTQzNzUwMCAtIEFQMkcgLSBjb21taXRtZW50CiMgUEJBTktBLTA4MzEwMDAgLSBNU1AxIC0gbGF0ZSBhc2V4dWFsCiMgUEJBTktBLTExMDIyMDAgLSBNU1A4IC0gZWFybHkgYXNleHVhbCAoZnJvbSBCb3pkZWNoIHBhcGVyKQojIFBCQU5LQS0wNzExOTAwIC0gSFNQNzAgLSBwcm9tb3RlciB1c2VkIGZvciBHRlAgYW5kIFJGUCBleHByZXNzaW9uIGluIHRoZSBtdXRhbnRzCiMgUEJBTktBLTE0MDA0MDAgLSBGQU1CIC0gcmluZyBtYXJrZXIgLSBkaXNjb3ZlcmVkIGJ5IGxvb2tpbmcgZm9yIG1hcmtlciBnZW5lcyBpbiBkYXRhCiMgUEJBTktBLTA3MjI2MDAgLSBGYW0tYjIgLSByaW5nIG1hcmtlciAtIGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzUxMTMwMzEvIAoKCm1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTMxOTUwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMoY2NwMiksICIoRmVtYWxlKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X01HMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDQxNjEwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKG1nMSksICIoTWFsZSkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9BUDJHIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhhcDJnKSwgIihDb21taXRtZW50KSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X01TUDEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTA4MzEwMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKG1zcDEpLCAiKFNjaGl6b250KSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X01TUDggPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTExMDIyMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKG1zcDgpLCAiKEFzZXh1YWwpIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkKCm1hcmtlcl9nZW5lX3Bsb3RfU0JQMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMTMwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZShpdGFsaWMoc2JwMSksICIoUmluZykiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKbWFya2VyX2dlbmVfcGxvdF9GQU1CIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzIyNjAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKGl0YWxpYyhmYW0tYjIpLCAgIihSaW5nKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpCgptYXJrZXJfZ2VuZV9wbG90X0hTUDcwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNzExOTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoaXRhbGljKEhTUDcwKSwgICIoUmVwb3J0ZXIpIiwiXG4iLCAiUEJBTktBXzA3MTE5MDAiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKCiMjIHBsb3QKIyMgY293cGxvdCBtZXRob2QKbWFya2VyX2dlbmVfcGxvdF9hbGwgPC0gcGxvdF9ncmlkKG1hcmtlcl9nZW5lX3Bsb3RfRkFNQiwgbWFya2VyX2dlbmVfcGxvdF9NU1A4LCBtYXJrZXJfZ2VuZV9wbG90X01TUDEsIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRywgbWFya2VyX2dlbmVfcGxvdF9DQ1AyLCBtYXJrZXJfZ2VuZV9wbG90X01HMSwgbWFya2VyX2dlbmVfcGxvdF9IU1A3MCwgbnJvdz0zKQoKbWFya2VyX2dlbmVfcGxvdF9hbGwKCiMjIHBhdGNod29yayBtZXRob2QKI21hcmtlcl9nZW5lX3Bsb3RfRkFNQiArIG1hcmtlcl9nZW5lX3Bsb3RfTVNQOCArIG1hcmtlcl9nZW5lX3Bsb3RfTVNQMSArIG1hcmtlcl9nZW5lX3Bsb3RfQVAyRyArIG1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiArIG1hcmtlcl9nZW5lX3Bsb3RfTUcxICsgbWFya2VyX2dlbmVfcGxvdF9IU1A3MApgYGAKCiMjIyMgRXhwcmVzc2lvbiAtIHJhdyAtIHB1cnBsZQpgYGB7ciwgZmlnLmhlaWdodCA9IDE1LCBmaWcud2lkdGggPSAxNX0KCm1hcmtlcl9nZW5lX3JhbXAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCIjRDNEM0QzIiwgIiMxRDE1NjQiKSkoNTApCgptYXJrZXJfZ2VuZV9wbG90X0NDUDIgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiUEJBTktBLTEzMTk1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIkNDUDIgKEZlbWFsZSkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfTUcxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wNDE2MTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiTUcxIChNYWxlKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9BUDJHIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0xNDM3NTAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJBUDJHIChDb21taXRtZW50KSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9NU1AxIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlBCQU5LQS0wODMxMDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNtaW4uY3V0b2ZmID0gInExIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJNU1AxIChTY2hpem9udCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfTVNQOCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMjIwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiTVNQOCAoQXNleHVhbCkiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfU0JQMSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTEwMTMwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiU0JQMSAoUmluZykiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkKCm1hcmtlcl9nZW5lX3Bsb3RfRkFNQiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDcyMjYwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbWluLmN1dG9mZiA9ICJxMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiRmFtLWIyIChSaW5nKSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKQoKbWFya2VyX2dlbmVfcGxvdF9IU1A3MCA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJQQkFOS0EtMDcxMTkwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI21pbi5jdXRvZmYgPSAicTEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCIoSFNQNzA7IFJlcG9ydGVyKSIsIlxuIiwgIlBCQU5LQV8wNzExOTAwIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApCgojIyBwbG90CiMjIGNvd3Bsb3QgbWV0aG9kCm1hcmtlcl9nZW5lX3Bsb3RfYWxsIDwtIHBsb3RfZ3JpZChtYXJrZXJfZ2VuZV9wbG90X0ZBTUIsIG1hcmtlcl9nZW5lX3Bsb3RfTVNQOCwgbWFya2VyX2dlbmVfcGxvdF9NU1AxLCBtYXJrZXJfZ2VuZV9wbG90X0FQMkcsIG1hcmtlcl9nZW5lX3Bsb3RfQ0NQMiwgbWFya2VyX2dlbmVfcGxvdF9NRzEsIG1hcmtlcl9nZW5lX3Bsb3RfSFNQNzAsIG5yb3c9MykKCm1hcmtlcl9nZW5lX3Bsb3RfYWxsCmBgYAoKIyMjIyBFeHByZXNzaW9uIC0gZGF0YSAtIHB1cnBsZQoKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgUEJBTktBLTE0MTgxMDAgICAgICAgIEdDU0tPLTE3ICBGRDMgICAKIyBQQkFOS0EtMDEwMjQwMCAgICAgICAgIEdDU0tPLTIgIE1EMyAKIyBQQkFOS0EtMDcxNjUwMCAgICAgICAgR0NTS08tMTkgIE1ENCAKIyBQQkFOS0EtMTQzNTIwMCAgICAgICAgR0NTS08tMjAgIEZENCAKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQ1CiMgUEJBTktBLTA4MjgwMDAgICAgICAgICBHQ1NLTy0zICBHRDEKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTExNDQ4MDAgICAgICAgIEdDU0tPLTI4ICBGRDUKCgptYXJrZXJfZ2VuZV9wbG90XzE3IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0MTgxMDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMiA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wMTAyNDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMyIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzE5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA3MTY1MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjAgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQzNTIwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDQiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKbWFya2VyX2dlbmVfcGxvdF8xMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wOTAyMzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImZkMiIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzEwIDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTA0MTM0MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMyA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0wODI4MDAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90X29vbSA8LSBGZWF0dXJlUGxvdCh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBkaW1zID0gYygxLDIpLCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gIlBCQU5LQS0xMzAyNzAwIiwgY29vcmQuZml4ZWQgPSBUUlVFLCAgcHQuc2l6ZSA9IDEsIG9yZGVyID0gVFJVRSkgKyAKICB0aGVtZV92b2lkKCkgKyAKICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhbWlseT0iQXJpYWwiLCBzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsKICAjIyBhZGQgc2V4IHN5bWJvbHMKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAzLjgsIHkgPSAxLjUsIGxhYmVsID0gbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIsIHkgPSAyLjgsIGxhYmVsID0gZmVtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpCgptYXJrZXJfZ2VuZV9wbG90XzI5IDwtIEZlYXR1cmVQbG90KHRlbnguanVzdHd0LmludGVncmF0ZWQsIGRpbXMgPSBjKDEsMiksIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZmVhdHVyZXMgPSAiUEJBTktBLTE0NDc5MDAiLCBjb29yZC5maXhlZCA9IFRSVUUsICBwdC5zaXplID0gMSwgb3JkZXIgPSBUUlVFKSArIAogIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFtaWx5PSJBcmlhbCIsIHNpemUgPSAyMCwgZmFjZSA9ICJib2xkIikpICsgCiAgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKwogICMjIGFkZCBzZXggc3ltYm9scwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDMuOCwgeSA9IDEuNSwgbGFiZWwgPSBtYWxlX3N5bWJvbCwgc2l6ZT03LCBjb2xvcj0iZ3JheSIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMiwgeSA9IDIuOCwgbGFiZWwgPSBmZW1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikKCm1hcmtlcl9nZW5lX3Bsb3RfMjEgPC0gRmVhdHVyZVBsb3QodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgZGltcyA9IGMoMSwyKSwgcmVkdWN0aW9uID0gInVtYXAiLCBmZWF0dXJlcyA9ICJQQkFOS0EtMTQ1NDgwMCIsIGNvb3JkLmZpeGVkID0gVFJVRSwgIHB0LnNpemUgPSAxLCBvcmRlciA9IFRSVUUpICsgCiAgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYW1pbHk9IkFyaWFsIiwgc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiKSkgKyAKICBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArCiAgIyMgYWRkIHNleCBzeW1ib2xzCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMy44LCB5ID0gMS41LCBsYWJlbCA9IG1hbGVfc3ltYm9sLCBzaXplPTcsIGNvbG9yPSJncmF5IikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyLCB5ID0gMi44LCBsYWJlbCA9IGZlbWFsZV9zeW1ib2wsIHNpemU9NywgY29sb3I9ImdyYXkiKQoKIyNvcmlnaW5hbCBsYWJlbDoKIyBsYWJzKHRpdGxlID0gcGFzdGUoIihDQ1AyOyBGZW1hbGUpIiwiXG4iLCAiUEJBTktBXzEzMTk1MDAiKSkKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKbXV0YW50X2V4cHJlc3Npb25fY29tcG9zaXRlIDwtIHdyYXBfcGxvdHMobWFya2VyX2dlbmVfcGxvdF8xNyAsIG1hcmtlcl9nZW5lX3Bsb3RfMiAsIG1hcmtlcl9nZW5lX3Bsb3RfMTkgLCBtYXJrZXJfZ2VuZV9wbG90XzIwICwgbWFya2VyX2dlbmVfcGxvdF8xMyAsIG1hcmtlcl9nZW5lX3Bsb3RfMTAgLCBtYXJrZXJfZ2VuZV9wbG90XzMgLCBtYXJrZXJfZ2VuZV9wbG90X29vbSAsIG1hcmtlcl9nZW5lX3Bsb3RfMjkgLCBtYXJrZXJfZ2VuZV9wbG90XzIxICwgbmNvbCA9IDQpCiAgICAgICAgICAgCiMjIHByaW50Cm11dGFudF9leHByZXNzaW9uX2NvbXBvc2l0ZQpgYGAKCiMgRGVuc2l0eSBQbG90cwoKIyMjIyBEZW5zaXR5IC0gcHVycGxlCgpgYGB7cn0KIyBQQkFOS0EtMTMxOTUwMCAtIENDUDIgLSBmZW1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTA0MTYxMDAgLSBNRzEgLSBkeW5lbmluIGhlYXZ5IGNoYWluIC0gbWFsZSAtIHVzZWQgaW4gODIwIGxpbmUKIyBQQkFOS0EtMTQzNzUwMCAtIEFQMkcgLSBjb21taXRtZW50CiMgUEJBTktBLTA4MzEwMDAgLSBNU1AxIC0gbGF0ZSBhc2V4dWFsCiMgUEJBTktBLTExMDIyMDAgLSBNU1A4IC0gZWFybHkgYXNleHVhbCAoZnJvbSBCb3pkZWNoIHBhcGVyKQojIFBCQU5LQS0wNzExOTAwIC0gSFNQNzAgLSBwcm9tb3RlciB1c2VkIGZvciBHRlAgYW5kIFJGUCBleHByZXNzaW9uIGluIHRoZSBtdXRhbnRzCiMgUEJBTktBLTE0MDA0MDAgLSBGQU1CIC0gcmluZyBtYXJrZXIgLSBkaXNjb3ZlcmVkIGJ5IGxvb2tpbmcgZm9yIG1hcmtlciBnZW5lcyBpbiBkYXRhCiMgUEJBTktBLTA3MjI2MDAgLSBGYW0tYjIgLSByaW5nIG1hcmtlciAtIGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzUxMTMwMzEvIAoKbWFya2Vyc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCmxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXMgPC0gcGxvdF9kZW5zaXR5KHRlbnguanVzdHd0LmludGVncmF0ZWQsIG1hcmtlcnNfbGlzdCwgam9pbnQgPSBGQUxTRSwgY29tYmluZSA9IEZBTFNFLCBkaW1zID0gYygxLDIpLCBwYWwgPSAicGxhc21hIiwgbWV0aG9kID0gImtzIikKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzIDwtIHdyYXBfcGxvdHMobGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMV1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiZ2QxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzNdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMiIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s0XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzZdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIm1kNSIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s3XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzldXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkMyIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1tYXJrZXJfZ2VuZV9yYW1wKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxMF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPW1hcmtlcl9nZW5lX3JhbXApICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA0KQoKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzCmBgYAoKCiMjIyMgRGVuc2l0eSAtdmlyaWRpcwoKYGBge3J9CiMgUEJBTktBLTEzMTk1MDAgLSBDQ1AyIC0gZmVtYWxlIC0gdXNlZCBpbiA4MjAgbGluZQojIFBCQU5LQS0wNDE2MTAwIC0gTUcxIC0gZHluZW5pbiBoZWF2eSBjaGFpbiAtIG1hbGUgLSB1c2VkIGluIDgyMCBsaW5lCiMgUEJBTktBLTE0Mzc1MDAgLSBBUDJHIC0gY29tbWl0bWVudAojIFBCQU5LQS0wODMxMDAwIC0gTVNQMSAtIGxhdGUgYXNleHVhbAojIFBCQU5LQS0xMTAyMjAwIC0gTVNQOCAtIGVhcmx5IGFzZXh1YWwgKGZyb20gQm96ZGVjaCBwYXBlcikKIyBQQkFOS0EtMDcxMTkwMCAtIEhTUDcwIC0gcHJvbW90ZXIgdXNlZCBmb3IgR0ZQIGFuZCBSRlAgZXhwcmVzc2lvbiBpbiB0aGUgbXV0YW50cwojIFBCQU5LQS0xNDAwNDAwIC0gRkFNQiAtIHJpbmcgbWFya2VyIC0gZGlzY292ZXJlZCBieSBsb29raW5nIGZvciBtYXJrZXIgZ2VuZXMgaW4gZGF0YQojIFBCQU5LQS0wNzIyNjAwIC0gRmFtLWIyIC0gcmluZyBtYXJrZXIgLSBodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM1MTEzMDMxLyAKCm1hcmtlcnNfbGlzdCA8LSBjKCJQQkFOS0EtMDgyODAwMCIsICJQQkFOS0EtMTMwMjcwMCIsICJQQkFOS0EtMTQ0NzkwMCIsICJQQkFOS0EtMDEwMjQwMCIsICJQQkFOS0EtMDcxNjUwMCIsICJQQkFOS0EtMDQxMzQwMCIsICJQQkFOS0EtMTQ1NDgwMCIsICJQQkFOS0EtMDkwMjMwMCIsICJQQkFOS0EtMTQxODEwMCIsICJQQkFOS0EtMTQzNTIwMCIpCgpsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzIDwtIHBsb3RfZGVuc2l0eSh0ZW54Lmp1c3R3dC5pbnRlZ3JhdGVkLCBtYXJrZXJzX2xpc3QsIGpvaW50ID0gRkFMU0UsIGNvbWJpbmUgPSBGQUxTRSwgZGltcyA9IGMoMSwyKSwgcGFsID0gInBsYXNtYSIsIG1ldGhvZCA9ICJrcyIpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90ClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcyA8LSB3cmFwX3Bsb3RzKGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzFdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbM11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSApKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbNl1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQ1IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbN11dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQxIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQyIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbOV1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQzIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMTBdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoImZkNCIpKSArIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3Vycz1jKCIjRENEQ0RDIiwgcGxhc21hKDMwKSkpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSA0KQoKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzCmBgYAoKIyMjIyBEZW5zaXR5IC0gdmlyaWRpcwpgYGB7ciwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyBQQkFOS0EtMDgyODAwMCAgICAgICAgIEdDU0tPLTMgIEdEMQoKIyBQQkFOS0EtMTMwMjcwMCAgICAgICBHQ1NLTy1vb20gIE1EMSAKIyBQQkFOS0EtMTQ0NzkwMCAgICAgICAgR0NTS08tMjkgIE1EMgojIFBCQU5LQS0wMTAyNDAwICAgICAgICAgR0NTS08tMiAgTUQzIAojIFBCQU5LQS0wNzE2NTAwICAgICAgICBHQ1NLTy0xOSAgTUQ0IAojIFBCQU5LQS0wNDEzNDAwICAgIEdDU0tPLTEwXzgyMCAgTUQ1CgojIFBCQU5LQS0xNDU0ODAwICAgICAgICBHQ1NLTy0yMSAgRkQxCiMgUEJBTktBLTA5MDIzMDAgICAgICAgIEdDU0tPLTEzICBGRDIKIyBQQkFOS0EtMTQxODEwMCAgICAgICAgR0NTS08tMTcgIEZEMyAgIAojIFBCQU5LQS0xNDM1MjAwICAgICAgICBHQ1NLTy0yMCAgRkQ0IAoKbWFya2Vyc19saXN0IDwtIGMoIlBCQU5LQS0wODI4MDAwIiwgIlBCQU5LQS0xMzAyNzAwIiwgIlBCQU5LQS0xNDQ3OTAwIiwgIlBCQU5LQS0wMTAyNDAwIiwgIlBCQU5LQS0wNzE2NTAwIiwgIlBCQU5LQS0wNDEzNDAwIiwgIlBCQU5LQS0xNDU0ODAwIiwgIlBCQU5LQS0wOTAyMzAwIiwgIlBCQU5LQS0xNDE4MTAwIiwgIlBCQU5LQS0xNDM1MjAwIikKCmxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXMgPC0gcGxvdF9kZW5zaXR5KHRlbnguanVzdHd0LmludGVncmF0ZWQsIG1hcmtlcnNfbGlzdCwgam9pbnQgPSBGQUxTRSwgY29tYmluZSA9IEZBTFNFLCBkaW1zID0gYygxLDIpLCBwYWwgPSAicGxhc21hIiwgbWV0aG9kID0gImtzIikKCiMjIG1ha2UgY29tcG9zaXRlIHBsb3QKVU1BUF9jb21wb3NpdGVfbXV0YW50X2dlbmVzIDwtIHdyYXBfcGxvdHMobGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMV1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiZ2QxIikpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbMl1dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIm1kMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1szXV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s0XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpICkrIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s1XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDQiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s2XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDUiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s3XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s4XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s5XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDMiKSkgKyBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9YygiI0RDRENEQyIsIHBsYXNtYSgzMCkpKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxMF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQpCgpVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMKCiMjIElGIHB1dHRpbmcgaW4gTUFJTiAtIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIGNvb3JkX2ZpeGVkKCkgKyB0aGVtZV92b2lkKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTkpKSArIGxhYnModGl0bGUgPSBwYXN0ZSgibWQxIikpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzPWMoIiNEQ0RDREMiLCBwbGFzbWEoMzApKSkgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC4zLCBiYXJoZWlnaHQgPSA0LjAsIHRpdGxlID0gIiIpKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIFBCQU5LQS0wODI4MDAwICAgICAgICAgR0NTS08tMyAgR0QxCgojIFBCQU5LQS0xMzAyNzAwICAgICAgIEdDU0tPLW9vbSAgTUQxIAojIFBCQU5LQS0xNDQ3OTAwICAgICAgICBHQ1NLTy0yOSAgTUQyCiMgUEJBTktBLTAxMDI0MDAgICAgICAgICBHQ1NLTy0yICBNRDMgCiMgUEJBTktBLTA3MTY1MDAgICAgICAgIEdDU0tPLTE5ICBNRDQgCiMgUEJBTktBLTA0MTM0MDAgICAgR0NTS08tMTBfODIwICBNRDUKCiMgUEJBTktBLTE0NTQ4MDAgICAgICAgIEdDU0tPLTIxICBGRDEKIyBQQkFOS0EtMDkwMjMwMCAgICAgICAgR0NTS08tMTMgIEZEMgojIFBCQU5LQS0xNDE4MTAwICAgICAgICBHQ1NLTy0xNyAgRkQzICAgCiMgUEJBTktBLTE0MzUyMDAgICAgICAgIEdDU0tPLTIwICBGRDQgCgptYXJrZXJzX2xpc3QgPC0gYygiUEJBTktBLTA4MjgwMDAiLCAiUEJBTktBLTEzMDI3MDAiLCAiUEJBTktBLTE0NDc5MDAiLCAiUEJBTktBLTAxMDI0MDAiLCAiUEJBTktBLTA3MTY1MDAiLCAiUEJBTktBLTA0MTM0MDAiLCAiUEJBTktBLTE0NTQ4MDAiLCAiUEJBTktBLTA5MDIzMDAiLCAiUEJBTktBLTE0MTgxMDAiLCAiUEJBTktBLTE0MzUyMDAiKQoKbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lcyA8LSBwbG90X2RlbnNpdHkodGVueC5qdXN0d3QuaW50ZWdyYXRlZCwgbWFya2Vyc19saXN0LCBqb2ludCA9IEZBTFNFLCBjb21iaW5lID0gRkFMU0UsIGRpbXMgPSBjKDEsMiksIHBhbCA9ICJwbGFzbWEiLCBtZXRob2QgPSAid2tkZSIsIHNsb3QgPSAnZGF0YScpCgojIyBtYWtlIGNvbXBvc2l0ZSBwbG90ClVNQVBfY29tcG9zaXRlX211dGFudF9nZW5lcyA8LSB3cmFwX3Bsb3RzKGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzFdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkX2ZpeGVkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUoImdkMSIpKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2NvbG91cmJhcihiYXJ3aWR0aCA9IDAuNSwgdGl0bGUgPSAiIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3Rfb2ZfZGVuc2l0eV9wbG90c19tdXRhbnRfZ2VuZXNbWzJdXSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDEiKSkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXNfc2VxdWVudGlhbChwYWxldHRlID0gIlB1cnBsZXMgMiIpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9vZl9kZW5zaXR5X3Bsb3RzX211dGFudF9nZW5lc1tbM11dICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZF9maXhlZCgpICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZV92b2lkKCkgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgibWQyIikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s0XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDMiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s1XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDQiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s2XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJtZDUiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s3XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDEiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s4XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDIiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1s5XV0gKyBjb29yZF9maXhlZCgpICsgdGhlbWVfdm9pZCgpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJmZDMiKSkgKyBzY2FsZV9jb2xvcl9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZSA9ICJQdXJwbGVzIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIHRpdGxlID0gIiIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X29mX2RlbnNpdHlfcGxvdHNfbXV0YW50X2dlbmVzW1sxMF1dICsgY29vcmRfZml4ZWQoKSArIHRoZW1lX3ZvaWQoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiZmQ0IikpICsgc2NhbGVfY29sb3JfY29udGludW91c19zZXF1ZW50aWFsKHBhbGV0dGUgPSAiUHVycGxlcyAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCB0aXRsZSA9ICIiKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDQpCgojIyBvbGQgY29sb3VyIHNjYWxlOiBzY2FsZV9jb2xvdXJfZ3JhZGllbnRuKGNvbG91cnM9bWFya2VyX2dlbmVfcmFtcCApCgpVTUFQX2NvbXBvc2l0ZV9tdXRhbnRfZ2VuZXMKYGBgCgoKCgoK